All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/10] arm: Add hafnium support
@ 2021-01-12 15:20 arunachalam.ganapathy
  2021-01-12 15:20 ` [PATCH 02/10] arm/trusted-firmware-a: Add support for spmd build option arunachalam.ganapathy
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: arunachalam.ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

Initial recipe for hafnium[1]. This enables build for reference Secure
Partition Manager (SPM) for systems that implement the Armv8.4-A
Secure-EL2 extension.

Link: [1] https://www.trustedfirmware.org/projects/hafnium/

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Ib256d8ca03c94131e308d962d786d5d6a656c256
---
 meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb | 74 +++++++++++++++++++++
 1 file changed, 74 insertions(+)
 create mode 100644 meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb

diff --git a/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb b/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
new file mode 100644
index 0000000..3a52599
--- /dev/null
+++ b/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
@@ -0,0 +1,74 @@
+SUMMARY = "Hafnium"
+DESCRIPTION = "A reference Secure Partition Manager (SPM) for systems that implement the Armv8.4-A Secure-EL2 extension"
+LICENSE = "BSD-3-Clause & GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=782b40c14bad5294672c500501edc103"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+inherit deploy python3native
+
+SRC_URI = "gitsm://git.trustedfirmware.org/hafnium/hafnium.git;protocol=https"
+SRCREV = "410a3acaf669c12d41fb4c57fcaf3ecee6fdba61"
+S = "${WORKDIR}/git"
+
+COMPATIBLE_MACHINE ?= "invalid"
+
+# Default build 'reference'
+HAFNIUM_PROJECT ?= "reference"
+
+# Platform must be set for each machine
+HAFNIUM_PLATFORM ?= "invalid"
+
+# hafnium build directory
+# Append _clang as the build rule in hafnium adds this to the platform name.
+HAFNIUM_BUILD_DIR_PLAT = "out/${HAFNIUM_PROJECT}/${HAFNIUM_PLATFORM}_clang"
+
+# do_deploy will install everything listed in this variable. It is set by
+# default to hafnium
+HAFNIUM_INSTALL_TARGET ?= "hafnium"
+
+DEPENDS = "bison-native bc-native"
+
+# set project to build
+EXTRA_OEMAKE += "PROJECT=${HAFNIUM_PROJECT}"
+
+do_compile_prepend() {
+    # Hafnium expects 'python'. Create symlink python to python3
+    real=$(which ${PYTHON})
+    ln -snf $real $(dirname $real)/python
+}
+
+do_install() {
+    install -d -m 755 ${D}/firmware
+    for bldfile in ${HAFNIUM_INSTALL_TARGET}; do
+        processed="0"
+        if [ -f ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.bin ]; then
+            echo "Install $bldfile.bin"
+            install -m 0755 ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.bin \
+                ${D}/firmware/$bldfile-${HAFNIUM_PLATFORM}.bin
+            ln -sf $bldfile-${HAFNIUM_PLATFORM}.bin ${D}/firmware/$bldfile.bin
+            processed="1"
+        fi
+        if [ -f ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.elf ]; then
+            echo "Install $bldfile.elf"
+            install -m 0755 ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.elf \
+                ${D}/firmware/$bldfile-${HAFNIUM_PLATFORM}.elf
+            ln -sf $bldfile-${HAFNIUM_PLATFORM}.elf ${D}/firmware/$bldfile.elf
+            processed="1"
+        fi
+        if [ "$processed" = "0" ]; then
+            bberror "Unsupported HAFNIUM_INSTALL_TARGET target $bldfile"
+            exit 1
+        fi
+    done
+}
+
+FILES_${PN} = "/firmware"
+SYSROOT_DIRS += "/firmware"
+# skip QA tests: {'ldflags'}
+INSANE_SKIP_${PN} = "ldflags"
+
+do_deploy() {
+    cp -rf ${D}/firmware/* ${DEPLOYDIR}/
+}
+addtask deploy after do_install
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 02/10] arm/trusted-firmware-a: Add support for spmd build option
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
@ 2021-01-12 15:20 ` arunachalam.ganapathy
  2021-01-12 15:20 ` [PATCH 03/10] arm-bsp/tc0: Add hafnium support Arunachalam Ganapathy
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: arunachalam.ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

This patch adds generic dispatcher 'spmd' option for SPD along with
SPMD_SPM_AT_SEL2 build option.

 Config: SPD=spmd and SPMD_SPM_AT_SEL2=1. Indicates the SPMC component
 runs at the S-EL2
   - Add hafnium dependency
   - Set CTX_INCLUDE_EL2_REGS=1 and ARM_ARCH_MINOR=4
   - Set BL32 to hafnium image
   - Set SP_LAYOUT_FILE and ARM_SPMC_MANIFEST build parameters

 Config: SPD=spmd and SPMD_SPM_AT_SEL2=0. Indicates the SPMC component
 runs at the S-EL1 execution state.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Icd3970e5132e75de67ef7f41dbfc8f9e1cdde7f3
---
 .../trusted-firmware-a/trusted-firmware-a.inc | 26 ++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a.inc b/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a.inc
index 48f5129..69d5ca8 100644
--- a/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a.inc
+++ b/meta-arm/recipes-bsp/trusted-firmware-a/trusted-firmware-a.inc
@@ -22,11 +22,20 @@ TFA_PLATFORM_aarch64_qemuall ?= "qemu"
 TFA_BOARD ?= ""
 
 # Some platforms use SPD (Secure Payload Dispatcher) services
-# Few options are "opteed", "tlkd", "trusty", "tspd"...
+# Few options are "opteed", "tlkd", "trusty", "tspd", "spmd"...
 # Leave empty to not use SPD
 TFA_SPD ?= ""
 TFA_SPD_aarch64_qemuall ?= "opteed"
 
+# Variable used when TFA_SPD=spmd
+TFA_SPMD_SPM_AT_SEL2 ?= "1"
+
+# SP layout file location. Used when TFA_SPD=spmd and TFA_SPMD_SPM_AT_SEL2=1
+TFA_SP_LAYOUT_FILE ?= ""
+
+# SPMC manifest file location. Used when TFA_SPD=spmd and TFA_SPMD_SPM_AT_SEL2=1
+TFA_ARM_SPMC_MANIFEST_DTS ?= ""
+
 # Build for debug (set TFA_DEBUG to 1 to activate)
 TFA_DEBUG ?= "0"
 
@@ -114,6 +123,9 @@ EXTRA_OEMAKE += "${@'TARGET_BOARD=${TFA_BOARD}' if d.getVar('TFA_BOARD') else ''
 # Handle TFA_SPD parameter
 EXTRA_OEMAKE += "${@'SPD=${TFA_SPD}' if d.getVar('TFA_SPD') else ''}"
 
+# If TFA_SPD is spmd, set SPMD_SPM_AT_SEL2
+EXTRA_OEMAKE += "${@'SPMD_SPM_AT_SEL2=${TFA_SPMD_SPM_AT_SEL2}' if d.getVar('TFA_SPD', True) == 'spmd' else ''}"
+
 # Handle TFA_DEBUG parameter
 EXTRA_OEMAKE += "${@bb.utils.contains('TFA_DEBUG', '1', 'DEBUG=${TFA_DEBUG}', '', d)}"
 
@@ -125,6 +137,18 @@ DEPENDS += " ${@bb.utils.contains('TFA_UBOOT', '1', 'u-boot', '', d)}"
 do_compile[depends] += " ${@bb.utils.contains('TFA_UBOOT', '1', 'u-boot:do_deploy', '', d)}"
 EXTRA_OEMAKE += "${@bb.utils.contains('TFA_UBOOT', '1', 'BL33=${DEPLOY_DIR_IMAGE}/u-boot.bin', '',d)}"
 
+# Hafnium support
+SEL2_SPMC = "${@'${TFA_SPMD_SPM_AT_SEL2}' if d.getVar('TFA_SPD', True) == 'spmd' else ''}"
+
+DEPENDS += " ${@bb.utils.contains('SEL2_SPMC', '1', 'hafnium', '', d)}"
+
+EXTRA_OEMAKE += "${@bb.utils.contains('SEL2_SPMC', '1', 'CTX_INCLUDE_EL2_REGS=1 ARM_ARCH_MINOR=4 BL32=${RECIPE_SYSROOT}/firmware/hafnium.bin', '', d)}"
+
+# Add SP layout file and spmc manifest for hafnium
+EXTRA_OEMAKE += "${@bb.utils.contains('SEL2_SPMC', '1', 'SP_LAYOUT_FILE=${TFA_SP_LAYOUT_FILE}' if d.getVar('TFA_SP_LAYOUT_FILE') else '', '', d)}"
+
+EXTRA_OEMAKE += "${@bb.utils.contains('SEL2_SPMC', '1', 'ARM_SPMC_MANIFEST_DTS=${TFA_ARM_SPMC_MANIFEST_DTS}' if d.getVar('TFA_ARM_SPMC_MANIFEST_DTS') else '', '', d)}"
+
 # Tell the tools where the native OpenSSL is located
 EXTRA_OEMAKE += "OPENSSL_DIR=${STAGING_DIR_NATIVE}/${prefix_native}"
 
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 03/10] arm-bsp/tc0: Add hafnium support
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
  2021-01-12 15:20 ` [PATCH 02/10] arm/trusted-firmware-a: Add support for spmd build option arunachalam.ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 04/10] arm-bsp/tc0: Add support for optee Arunachalam Ganapathy
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

Enables hafnium support for tc0.
Adds pending patches for SEL1 SP support.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: If5c12b7e7b7a301ae9a48a88223be3e51f38d3aa
---
 ...condary-core-entry-point-at-SPMC-ini.patch | 324 ++++++++++++++++++
 ...A-Cold-boot-and-wake-up-from-suspend.patch |  65 ++++
 ...-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch |  87 +++++
 .../recipes-bsp/hafnium/hafnium-tc0.inc       |  19 +
 .../recipes-bsp/hafnium/hafnium_2.4.bbappend  |   6 +
 5 files changed, 501 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
 create mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
 create mode 100644 meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
 create mode 100644 meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
 create mode 100644 meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend

diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
new file mode 100644
index 0000000..5828750
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch
@@ -0,0 +1,324 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From cb329ce33874abd8b69988c3dc63fd323a3413be Mon Sep 17 00:00:00 2001
+From: Max Shvetsov <maksims.svecovs@arm.com>
+Date: Thu, 27 Aug 2020 12:37:57 +0100
+Subject: [PATCH 1/4] FF-A: Register secondary core entry point at SPMC init.
+
+When the primary physical core boots the SPMC registers its secondary physical
+core entry points to the SPMD. All Secure Partition are then initialized on
+their primary Execution Contexts. A Secure Partition calls PSCI_CPU_ON from its
+first EC (trapped to the SPMC) passing entry point addresses of secondary ECs.
+ECs are turned "on" in their SPMC internal states, although they do not run yet
+(the service call does not reach the EL3 PSCI layer). Later, when the NWd
+(Hypervisor or OS Kernel) boots, it calls PSCI_CPU_ON for waking up physical
+cores down to EL3. The PSCI layer calls into SPMD PM hooks, then the SPMD calls
+into the SPMC by an exception return to the registered secondary entry point.
+The target secondary core then reaches Hafnium vcpu_main.
+
+Change-Id: I2bd42ea54e1a7feebff20e878345ec196ff352e9
+Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
+Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
+---
+ inc/hf/arch/init.h                          |   7 ++
+ src/arch/aarch64/hypervisor/psci_handler.c  | 131 +++++++++++++++++---
+ src/arch/aarch64/inc/hf/arch/spmd_helpers.h |  15 +++
+ src/cpu.c                                   |   7 ++
+ src/init.c                                  |   2 +
+ 5 files changed, 143 insertions(+), 19 deletions(-)
+ create mode 100644 src/arch/aarch64/inc/hf/arch/spmd_helpers.h
+
+diff --git a/inc/hf/arch/init.h b/inc/hf/arch/init.h
+index 5205e4e..ef0e48f 100644
+--- a/inc/hf/arch/init.h
++++ b/inc/hf/arch/init.h
+@@ -8,6 +8,8 @@
+ 
+ #pragma once
+ 
++#include "hf/boot_params.h"
++
+ /**
+  * Performs arch specific boot time initialization.
+  *
+@@ -15,3 +17,8 @@
+  * possible.
+  */
+ void arch_one_time_init(void);
++
++/**
++ * Sets up secondary cores.
++ */
++void arch_psci_secondary_core_init(const struct boot_params *params);
+diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
+index f89a00b..bdcc1d3 100644
+--- a/src/arch/aarch64/hypervisor/psci_handler.c
++++ b/src/arch/aarch64/hypervisor/psci_handler.c
+@@ -11,9 +11,11 @@
+ #include <stdint.h>
+ 
+ #include "hf/arch/plat/psci.h"
++#include "hf/arch/spmd_helpers.h"
+ #include "hf/arch/types.h"
+ 
+ #include "hf/api.h"
++#include "hf/boot_params.h"
+ #include "hf/cpu.h"
+ #include "hf/dlog.h"
+ #include "hf/ffa.h"
+@@ -24,9 +26,32 @@
+ #include "smc.h"
+ 
+ static uint32_t el3_psci_version;
++static ffa_vm_id_t physical_ffa_id;
+ 
+ void cpu_entry(struct cpu *c);
+ 
++#if SECURE_WORLD == 1
++
++static void set_ffa_id(void)
++{
++	struct ffa_value res =
++		smc_ffa_call((struct ffa_value){.func = FFA_ID_GET_32});
++
++	if (res.func != FFA_SUCCESS_32) {
++		dlog_error("%s Failed to get it's own FF-A ID.\n", __func__);
++		physical_ffa_id = HF_INVALID_VM_ID;
++		return;
++	}
++	physical_ffa_id = res.arg2 & 0xFFFF;
++}
++
++#endif
++
++ffa_vm_id_t get_ffa_id(void)
++{
++	return physical_ffa_id;
++}
++
+ /* Performs arch specific boot time initialisation. */
+ void arch_one_time_init(void)
+ {
+@@ -53,9 +78,79 @@ void arch_one_time_init(void)
+ 	}
+ #else
+ 	el3_psci_version = PSCI_VERSION_1_1;
++
++	set_ffa_id();
+ #endif
+ }
+ 
++/**
++ * Register secondary physical core entry points to the SPMD.
++ */
++void arch_psci_secondary_core_init(const struct boot_params *params)
++{
++#if SECURE_WORLD == 1
++	struct ffa_value res;
++
++	for (uint32_t count = 0; count < params->cpu_count; count++) {
++		uint32_t id = params->cpu_ids[count];
++		struct cpu *cpu = cpu_find(id);
++		const ffa_vm_id_t ffa_id = get_ffa_id();
++
++		res = smc_ffa_call((struct ffa_value){
++			.func = FFA_MSG_SEND_DIRECT_REQ_32,
++			.arg1 = (ffa_id << 16) | SPMD_ID,
++			.arg3 = SPMD_DIRECT_MSG_SET_ENTRY_POINT,
++			.arg4 = params->cpu_ids[count],
++			.arg5 = (uintreg_t)&cpu_entry,
++			.arg6 = (uintreg_t)cpu});
++
++		if (res.func != FFA_SUCCESS_32) {
++			dlog_warning(
++				"%s Failed to initialize secondary core ID: "
++				"%u\n",
++				__func__, id);
++		}
++
++		dlog_verbose("SPMD EP register returned %#x\n", res.func);
++	}
++#endif
++}
++
++/**
++ * Convert a PSCI CPU / affinity ID for a secondary VM to the corresponding vCPU
++ * index.
++ */
++ffa_vcpu_index_t vcpu_id_to_index(cpu_id_t vcpu_id)
++{
++	/* For now we use indices as IDs for the purposes of PSCI. */
++	return vcpu_id;
++}
++
++#if SECURE_WORLD == 1
++/**
++ * Use vcpu_on only as a way to initialize entry point without
++ * an intent to power up vcpu.
++ */
++static uintreg_t ffa_register_entrypoint(cpu_id_t id, struct vm *vm,
++					 uintreg_t entrypoint, uintreg_t param)
++{
++	ffa_vcpu_index_t target_vcpu_index = vcpu_id_to_index(id);
++
++	if (target_vcpu_index >= vm->vcpu_count) {
++		return PSCI_ERROR_INVALID_PARAMETERS;
++	}
++
++	struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
++	struct vcpu_locked locked_target_vcpu = vcpu_lock(target_vcpu);
++
++	vcpu_on(locked_target_vcpu, ipa_init(entrypoint), param);
++
++	vcpu_unlock(&locked_target_vcpu);
++
++	return PSCI_RETURN_SUCCESS;
++}
++#endif
++
+ /**
+  * Handles PSCI requests received via HVC or SMC instructions from the primary
+  * VM.
+@@ -180,7 +275,8 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
+ 		panic("CPU off failed");
+ 		break;
+ 
+-	case PSCI_CPU_ON:
++	case PSCI_CPU_ON: {
++#if SECURE_WORLD == 0
+ 		c = cpu_find(arg0);
+ 		if (!c) {
+ 			*ret = PSCI_ERROR_INVALID_PARAMETERS;
+@@ -208,7 +304,12 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
+ 		if (*ret != PSCI_RETURN_SUCCESS) {
+ 			cpu_off(c);
+ 		}
++#else
++		*ret = ffa_register_entrypoint((cpu_id_t)arg0, vcpu->vm, arg1,
++					       arg2);
++#endif
+ 		break;
++	}
+ 
+ 	case PSCI_MIGRATE:
+ 	case PSCI_MIGRATE_INFO_TYPE:
+@@ -234,16 +335,6 @@ bool psci_primary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
+ 	return true;
+ }
+ 
+-/**
+- * Convert a PSCI CPU / affinity ID for a secondary VM to the corresponding vCPU
+- * index.
+- */
+-ffa_vcpu_index_t vcpu_id_to_index(cpu_id_t vcpu_id)
+-{
+-	/* For now we use indices as IDs for the purposes of PSCI. */
+-	return vcpu_id;
+-}
+-
+ /**
+  * Handles PSCI requests received via HVC or SMC instructions from a secondary
+  * VM.
+@@ -337,22 +428,23 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
+ 	case PSCI_CPU_ON: {
+ 		/* Parameter names as per PSCI specification. */
+ 		cpu_id_t target_cpu = arg0;
+-		ipaddr_t entry_point_address = ipa_init(arg1);
+ 		uint64_t context_id = arg2;
+-		ffa_vcpu_index_t target_vcpu_index =
+-			vcpu_id_to_index(target_cpu);
+ 		struct vm *vm = vcpu->vm;
+-		struct vcpu *target_vcpu;
+ 
++#if SECURE_WORLD == 1
++		*ret = ffa_register_entrypoint((cpu_id_t)target_cpu, vm, arg1,
++					       context_id);
++#else
++		ffa_vcpu_index_t target_vcpu_index =
++			vcpu_id_to_index(target_cpu);
+ 		if (target_vcpu_index >= vm->vcpu_count) {
+ 			*ret = PSCI_ERROR_INVALID_PARAMETERS;
+ 			break;
+ 		}
++		struct vcpu *target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
+ 
+-		target_vcpu = vm_get_vcpu(vm, target_vcpu_index);
+-
+-		if (vcpu_secondary_reset_and_start(
+-			    target_vcpu, entry_point_address, context_id)) {
++		if (vcpu_secondary_reset_and_start(target_vcpu, ipa_init(arg1),
++						   context_id)) {
+ 			/*
+ 			 * Tell the scheduler that it can start running the new
+ 			 * vCPU now.
+@@ -362,6 +454,7 @@ bool psci_secondary_vm_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
+ 		} else {
+ 			*ret = PSCI_ERROR_ALREADY_ON;
+ 		}
++#endif
+ 
+ 		break;
+ 	}
+diff --git a/src/arch/aarch64/inc/hf/arch/spmd_helpers.h b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
+new file mode 100644
+index 0000000..6e11c36
+--- /dev/null
++++ b/src/arch/aarch64/inc/hf/arch/spmd_helpers.h
+@@ -0,0 +1,15 @@
++/*
++ * Copyright 2020 The Hafnium Authors.
++ *
++ * Use of this source code is governed by a BSD-style
++ * license that can be found in the LICENSE file or at
++ * https://opensource.org/licenses/BSD-3-Clause.
++ */
++
++#define SPMD_ID 0xFFFF
++#define SPMD_DIRECT_MSG_SET_ENTRY_POINT 1
++
++/**
++ * Get SPMC ID stored in the manifest.
++ */
++ffa_vm_id_t get_ffa_id(void);
+diff --git a/src/cpu.c b/src/cpu.c
+index 0a3fc6f..42a17fa 100644
+--- a/src/cpu.c
++++ b/src/cpu.c
+@@ -138,6 +138,8 @@ bool cpu_on(struct cpu *c, ipaddr_t entry, uintreg_t arg)
+ 	c->is_on = true;
+ 	sl_unlock(&c->lock);
+ 
++#if SECURE_WORLD == 0
++
+ 	if (!prev) {
+ 		struct vm *vm = vm_find(HF_PRIMARY_VM_ID);
+ 		struct vcpu *vcpu = vm_get_vcpu(vm, cpu_index(c));
+@@ -148,6 +150,11 @@ bool cpu_on(struct cpu *c, ipaddr_t entry, uintreg_t arg)
+ 		vcpu_unlock(&vcpu_locked);
+ 	}
+ 
++#else
++	(void)entry;
++	(void)arg;
++#endif
++
+ 	return prev;
+ }
+ 
+diff --git a/src/init.c b/src/init.c
+index a5b48ab..0121213 100644
+--- a/src/init.c
++++ b/src/init.c
+@@ -146,6 +146,8 @@ void one_time_init(void)
+ 
+ 	cpu_module_init(params.cpu_ids, params.cpu_count);
+ 
++	arch_psci_secondary_core_init(&params);
++
+ 	/* Load all VMs. */
+ 	update.reserved_ranges_count = 0;
+ 	if (!load_vms(mm_stage1_locked, &manifest, &cpio, &params, &update,
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
new file mode 100644
index 0000000..0b58637
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch
@@ -0,0 +1,65 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 8422e2a5d6b2094f9f451a2d818a593cba29af84 Mon Sep 17 00:00:00 2001
+From: Max Shvetsov <maksims.svecovs@arm.com>
+Date: Thu, 27 Aug 2020 12:39:50 +0100
+Subject: [PATCH 2/4] FF-A: Cold boot and wake up from suspend.
+
+WIP: Currently there is zero entry-point passed with no arguments, This
+will be reworked once a proper way to pass this information will be
+defined.
+
+Change-Id: Ic6050af16d4081ca31729744995fbb999b170e11
+Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
+---
+ src/main.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/src/main.c b/src/main.c
+index 5f30aac..7b7264f 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -7,6 +7,7 @@
+  */
+ 
+ #include "hf/cpu.h"
++#include "hf/dlog.h"
+ #include "hf/vm.h"
+ 
+ /**
+@@ -16,9 +17,31 @@
+ struct vcpu *cpu_main(struct cpu *c)
+ {
+ 	struct vcpu *vcpu;
++
+ #if SECURE_WORLD == 1
+ 	struct vm *first_boot = vm_get_first_boot();
+ 
++	if (c->is_on == false) {
++		/*
++		 * This is the PSCI warm reset path (svc_cpu_on_finish
++		 * handler relayed by SPMD). Notice currenty the "first_boot"
++		 * VM is resumed on any CPU on event.
++		 */
++		(void)cpu_on(c, ipa_init(0UL), 0UL);
++		dlog_verbose("%s: cpu mpidr 0x%x on\n", __func__, c->id);
++	}
++
++	/*
++	 * If `vm_get_first_boot` returns a valid vm, the first partition to
++	 * execute is in accordance to the boot-order field of the partition's
++	 * manifest.
++	 * Else, no partition has been configured with the "boot-order" field
++	 * in its manifest, and primary vm should be booted.
++	 */
++	if (!first_boot) {
++		first_boot = vm_find(HF_PRIMARY_VM_ID);
++	}
++
+ 	vcpu = vm_get_vcpu(first_boot, cpu_index(c));
+ #else
+ 	vcpu = vm_get_vcpu(vm_find(HF_PRIMARY_VM_ID), cpu_index(c));
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
new file mode 100644
index 0000000..83aeca3
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/hafnium/files/tc0/0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch
@@ -0,0 +1,87 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 66d7628fea54dd7a25d25a13eb4f732c0a3428d0 Mon Sep 17 00:00:00 2001
+From: Max Shvetsov <maksims.svecovs@arm.com>
+Date: Fri, 18 Sep 2020 13:52:20 +0100
+Subject: [PATCH 3/4] FF-A: Respond to PSCI_CPU_OFF from SPMD.
+
+At run-time when a PSCI call is made from NWd, the corresponding SPMD PM
+hooks gets called and is eventually routed to the SPMC.  This change
+implements a generic "SPMD handler" processing PM events that may be
+conveyed from SPMD to SPMC such as core suspend, core off.
+
+Change-Id: Id288e26d9fbb8328acc71f5cf68c39e095a0e3da
+Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
+---
+ src/arch/aarch64/hypervisor/handler.c | 40 ++++++++++++++++++++++++++-
+ 1 file changed, 39 insertions(+), 1 deletion(-)
+
+diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
+index c10f77e..95d6a18 100644
+--- a/src/arch/aarch64/hypervisor/handler.c
++++ b/src/arch/aarch64/hypervisor/handler.c
+@@ -13,6 +13,7 @@
+ #include "hf/arch/mmu.h"
+ #include "hf/arch/other_world.h"
+ #include "hf/arch/plat/smc.h"
++#include "hf/arch/spmd_helpers.h"
+ 
+ #include "hf/api.h"
+ #include "hf/check.h"
+@@ -478,6 +479,41 @@ static bool ffa_handler(struct ffa_value *args, struct vcpu *current,
+ 
+ #if SECURE_WORLD == 1
+ 
++/**
++ * Returns true if the message is sent directly from SPMD to SPMC.
++ */
++static bool is_spmd_message(const uint64_t arg)
++{
++	return (((arg & 0xFFFF) == get_ffa_id()) &&
++		(((arg >> 16) & 0xFFFF) == SPMD_ID));
++}
++
++/**
++ * Handle special direct messages from SPMD to SPMC. For now related to power
++ * management only.
++ */
++static bool spmd_handler(struct ffa_value *ret)
++{
++	if (!is_spmd_message(ret->arg1)) {
++		return false;
++	}
++
++	dlog_verbose("%s Handling direct PSCI calls from SPMD\n", __func__);
++
++	switch (ret->arg3) {
++	case PSCI_CPU_OFF:
++		ret->func = FFA_MSG_SEND_DIRECT_RESP_32;
++		ret->arg1 = (get_ffa_id() << 16) | SPMD_ID;
++		ret->arg2 = 0U;
++		break;
++	default:
++		dlog_verbose("Following message not handled %#x\n", ret->arg3);
++		return false;
++	}
++
++	return true;
++}
++
+ /**
+  * Called to switch to the other world and handle FF-A calls from it. Returns
+  * when it is ready to run a secure partition again.
+@@ -510,7 +546,9 @@ static void other_world_switch_loop(struct vcpu *other_world_vcpu,
+ 		 * the result of the call back to EL3 unless the API handler
+ 		 * sets *next to something different.
+ 		 */
+-		if (!ffa_handler(&other_world_args, other_world_vcpu, next)) {
++
++		if (!spmd_handler(&other_world_args) &&
++		    !ffa_handler(&other_world_args, other_world_vcpu, next)) {
+ 			other_world_args.func = SMCCC_ERROR_UNKNOWN;
+ 		}
+ 	}
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc b/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
new file mode 100644
index 0000000..51747ce
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/hafnium/hafnium-tc0.inc
@@ -0,0 +1,19 @@
+# TC0 specific configuration
+
+# Intermediate SHA with 2.4 baseline version
+SRCREV = "ee68c5494dea5c5a59aa02af46b35ab3d949672e"
+PV = "2.4+git${SRCPV}"
+
+FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/tc0:"
+
+SRC_URI_append = " \
+    file://0001-FF-A-Register-secondary-core-entry-point-at-SPMC-ini.patch \
+    file://0002-FF-A-Cold-boot-and-wake-up-from-suspend.patch \
+    file://0003-FF-A-Respond-to-PSCI_CPU_OFF-from-SPMD.patch \
+    "
+
+COMPATIBLE_MACHINE = "tc0"
+
+HAFNIUM_PROJECT = "reference"
+HAFNIUM_PLATFORM = "secure_tc0"
+HAFNIUM_INSTALL_TARGET = "hafnium"
diff --git a/meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend b/meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend
new file mode 100644
index 0000000..a6e6874
--- /dev/null
+++ b/meta-arm-bsp/recipes-bsp/hafnium/hafnium_2.4.bbappend
@@ -0,0 +1,6 @@
+# Machine specific configurations
+
+MACHINE_HAFNIUM_REQUIRE ?= ""
+MACHINE_HAFNIUM_REQUIRE_tc0 = "hafnium-tc0.inc"
+
+require ${MACHINE_HAFNIUM_REQUIRE}
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 04/10] arm-bsp/tc0: Add support for optee
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
  2021-01-12 15:20 ` [PATCH 02/10] arm/trusted-firmware-a: Add support for spmd build option arunachalam.ganapathy
  2021-01-12 15:20 ` [PATCH 03/10] arm-bsp/tc0: Add hafnium support Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 05/10] arm-bsp/tc0: Add tc0 platform support patches " Arunachalam Ganapathy
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

This patch adds optee-os, optee-client, optee-test support in tc0 bsp.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I65f795b7ec2b4def4778b286b2f744b06b177157
---
 .../recipes-security/optee/optee-client-tc0.inc  |  5 +++++
 .../optee/optee-client_3.11.0.bbappend           |  6 ++++++
 .../recipes-security/optee/optee-os-tc0.inc      | 16 ++++++++++++++++
 .../optee/optee-os_3.11.0.bbappend               |  6 ++++++
 .../recipes-security/optee/optee-test-tc0.inc    | 14 ++++++++++++++
 .../optee/optee-test_3.11.0.bbappend             |  6 ++++++
 6 files changed, 53 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
 create mode 100644 meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend

diff --git a/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
new file mode 100644
index 0000000..8b13386
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
@@ -0,0 +1,5 @@
+# TC0 specific configuration
+
+# Intermediate SHA with 3.11 baseline version
+SRCREV = "3f44b870299514ad8c6b7dee776eb2994d9c1cd4"
+PV = "3.11.0+git${SRCPV}"
diff --git a/meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend
new file mode 100644
index 0000000..fa4fd69
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-client_3.11.0.bbappend
@@ -0,0 +1,6 @@
+# Machine specific configurations
+
+MACHINE_OPTEE_CLIENT_REQUIRE ?= ""
+MACHINE_OPTEE_CLIENT_REQUIRE_tc0 = "optee-client-tc0.inc"
+
+require ${MACHINE_OPTEE_CLIENT_REQUIRE}
diff --git a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
new file mode 100644
index 0000000..a700daf
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
@@ -0,0 +1,16 @@
+# TC0 specific configuration
+
+# Intermediate SHA with 3.11 baseline version
+SRCREV = "3284d935bc7e7bf7abfb5b19394a387d975d6dd4"
+PV = "3.11.0+git${SRCPV}"
+
+# This is incorporated into the SRCREV above
+SRC_URI_remove = " \
+    file://0001-libutils-provide-empty-__getauxval-implementation.patch \
+    file://0002-link.mk-implement-support-for-libnames-after-libgcc-.patch \
+    file://0003-ta_dev_kit.mk-make-sure-that-libutils-is-linked-seco.patch \
+"
+
+COMPATIBLE_MACHINE = "tc0"
+
+OPTEEMACHINE = "totalcompute-tc0"
diff --git a/meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend
new file mode 100644
index 0000000..7b96a4d
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-os_3.11.0.bbappend
@@ -0,0 +1,6 @@
+# Machine specific configurations
+
+MACHINE_OPTEE_OS_REQUIRE ?= ""
+MACHINE_OPTEE_OS_REQUIRE_tc0 = "optee-os-tc0.inc"
+
+require ${MACHINE_OPTEE_OS_REQUIRE}
diff --git a/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
new file mode 100644
index 0000000..cca5076
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-test-tc0.inc
@@ -0,0 +1,14 @@
+# TC0 specific configuration
+
+# Intermediate SHA with 3.11 baseline version
+SRCREV = "b35df64954ef96e09c0d5573014f4d1432dbc92f"
+PV = "3.11.0+git${SRCPV}"
+
+# This is incorporated into the SRCREV above
+SRC_URI_remove = " \
+    file://0001-host-xtest-Adjust-order-of-including-compiler.h.patch \
+    file://0002-make-remove-Wno-unsafe-loop-for-clang.patch \
+    file://0003-make-remove-Wmissing-noreturn-for-clang.patch \
+"
+
+COMPATIBLE_MACHINE = "tc0"
diff --git a/meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend b/meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend
new file mode 100644
index 0000000..4fd1cde
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/optee-test_3.11.0.bbappend
@@ -0,0 +1,6 @@
+# Machine specific configurations
+
+MACHINE_OPTEE_TEST_REQUIRE ?= ""
+MACHINE_OPTEE_TEST_REQUIRE_tc0 = "optee-test-tc0.inc"
+
+require ${MACHINE_OPTEE_TEST_REQUIRE}
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 05/10] arm-bsp/tc0: Add tc0 platform support patches for optee
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (2 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 04/10] arm-bsp/tc0: Add support for optee Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 06/10] arm-bsp/tc0: Enable optee core with SPMC at SEL2 Arunachalam Ganapathy
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

These patches in optee-os adds support for
      - tc0 platform
      - SEL2 SPMC support in optee core
      - support for tc0 SEL2 SPMC config

The patch in optee-client adds support for
    - allocating page aligned shmem buffers

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I1cfe134bdcedc45adf446f46af0d2881815b98f6
---
 ...void-memcpy-when-using-TEEC_TempMemo.patch |  52 ++
 ...e-page-aligned-shared-memory-buffers.patch |  95 +++
 ...ore-SPMC-update-for-FF-A-version-1.0.patch |  50 ++
 .../tc0/0002-core-add-thread_smccc.patch      |  89 +++
 ...e-enable-SPCI-with-SPM-Core-at-S-EL2.patch | 623 ++++++++++++++++++
 ...fixes-to-align-with-upstream-hafnium.patch | 188 ++++++
 ...e-arm-Total-Compute-platform-support.patch | 187 ++++++
 ...alcompute-Add-support-for-S-EL2-SPMC.patch | 108 +++
 ...e-add-optee-manifest-file-and-sp-lay.patch |  73 ++
 ...e-define-tzdram-start-address-for-S-.patch |  36 +
 .../optee/optee-client-tc0.inc                |   7 +
 .../recipes-security/optee/optee-os-tc0.inc   |  15 +-
 12 files changed, 1522 insertions(+), 1 deletion(-)
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
 create mode 100644 meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch

diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
new file mode 100644
index 0000000..4515c1d
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch
@@ -0,0 +1,52 @@
+Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_client/commit/7e569bdf770f635c5de1f4e659d41039a6199a0b]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 7e569bdf770f635c5de1f4e659d41039a6199a0b Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Wed, 11 Nov 2020 10:09:38 +0100
+Subject: [PATCH 1/2] Revert "libteec: Avoid memcpy() when using
+ TEEC_TempMemoryReference"
+
+This reverts commit dcb13e2f457fa98e9ba49dd2a364542680671e95.
+---
+ libteec/src/tee_client_api.c | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+diff --git a/libteec/src/tee_client_api.c b/libteec/src/tee_client_api.c
+index 6b81e09..b8ccdfa 100644
+--- a/libteec/src/tee_client_api.c
++++ b/libteec/src/tee_client_api.c
+@@ -217,15 +217,11 @@ static TEEC_Result teec_pre_process_tmpref(TEEC_Context *ctx,
+ 			MEMREF_SHM_ID(param) = shm->id;
+ 		}
+ 	} else {
+-		shm->buffer = tmpref->buffer;
+-		res = TEEC_RegisterSharedMemory(ctx, shm);
++		res = TEEC_AllocateSharedMemory(ctx, shm);
+ 		if (res != TEEC_SUCCESS)
+ 			return res;
+ 
+-		if (shm->shadow_buffer)
+-			memcpy(shm->shadow_buffer, tmpref->buffer,
+-			       tmpref->size);
+-
++		memcpy(shm->buffer, tmpref->buffer, tmpref->size);
+ 		MEMREF_SHM_ID(param) = shm->id;
+ 	}
+ 
+@@ -388,10 +384,8 @@ static void teec_post_process_tmpref(uint32_t param_type,
+ 			TEEC_SharedMemory *shm)
+ {
+ 	if (param_type != TEEC_MEMREF_TEMP_INPUT) {
+-		if (MEMREF_SIZE(param) <= tmpref->size && tmpref->buffer &&
+-		    shm->shadow_buffer)
+-			memcpy(tmpref->buffer, shm->shadow_buffer,
+-			       MEMREF_SIZE(param));
++		if (MEMREF_SIZE(param) <= tmpref->size && tmpref->buffer)
++			memcpy(tmpref->buffer, shm->buffer, MEMREF_SIZE(param));
+ 
+ 		tmpref->size = MEMREF_SIZE(param);
+ 	}
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
new file mode 100644
index 0000000..5928bfd
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-client/tc0/0002-Allocate-page-aligned-shared-memory-buffers.patch
@@ -0,0 +1,95 @@
+Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_client/commit/7a67f8b7681ecf3abb5b09e5e320857d16f4a7e6]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 7a67f8b7681ecf3abb5b09e5e320857d16f4a7e6 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Mon, 16 Nov 2020 17:34:07 +0100
+Subject: [PATCH 2/2] Allocate page aligned shared memory buffers
+
+Allocate page aligned shared memory buffer guarantee that each shared
+memory buffer doesn't accidentally share a page of memory or they may
+become aliased when mapped in secure world. This is normally not a big
+problem but may make it a bit harder to track down buffer overruns in
+shared memory buffers.
+
+In a post Arm v8.4 architecture with FF-A [1] there's trouble since it's
+not permitted to share the same physical page twice.
+
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+---
+ libteec/src/tee_client_api.c        | 14 ++++++++++++--
+ tee-supplicant/src/tee_supplicant.c | 12 +++++++++++-
+ 2 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/libteec/src/tee_client_api.c b/libteec/src/tee_client_api.c
+index b8ccdfa..676d373 100644
+--- a/libteec/src/tee_client_api.c
++++ b/libteec/src/tee_client_api.c
+@@ -74,6 +74,16 @@ static void teec_mutex_unlock(pthread_mutex_t *mu)
+ 	pthread_mutex_unlock(mu);
+ }
+ 
++static void *teec_paged_aligned_alloc(size_t sz)
++{
++	void *p = NULL;
++
++	if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
++		return p;
++
++	return NULL;
++}
++
+ static int teec_open_dev(const char *devname, const char *capabilities,
+ 			 uint32_t *gen_caps)
+ {
+@@ -790,7 +800,7 @@ TEEC_Result TEEC_RegisterSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
+ 		 * we're not making matters worse by trying to allocate and
+ 		 * register a shadow buffer before giving up.
+ 		 */
+-		shm->shadow_buffer = malloc(s);
++		shm->shadow_buffer = teec_paged_aligned_alloc(s);
+ 		if (!shm->shadow_buffer)
+ 			return TEEC_ERROR_OUT_OF_MEMORY;
+ 		fd = teec_shm_register(ctx->fd, shm->shadow_buffer, s,
+@@ -873,7 +883,7 @@ TEEC_Result TEEC_AllocateSharedMemory(TEEC_Context *ctx, TEEC_SharedMemory *shm)
+ 		s = 8;
+ 
+ 	if (ctx->reg_mem) {
+-		shm->buffer = malloc(s);
++		shm->buffer = teec_paged_aligned_alloc(s);
+ 		if (!shm->buffer)
+ 			return TEEC_ERROR_OUT_OF_MEMORY;
+ 
+diff --git a/tee-supplicant/src/tee_supplicant.c b/tee-supplicant/src/tee_supplicant.c
+index 94cf382..d590c2b 100644
+--- a/tee-supplicant/src/tee_supplicant.c
++++ b/tee-supplicant/src/tee_supplicant.c
+@@ -127,6 +127,16 @@ static size_t num_waiters_dec(struct thread_arg *arg)
+ 	return ret;
+ }
+ 
++static void *paged_aligned_alloc(size_t sz)
++{
++	void *p = NULL;
++
++	if (!posix_memalign(&p, sysconf(_SC_PAGESIZE), sz))
++		return p;
++
++	return NULL;
++}
++
+ static int get_value(size_t num_params, struct tee_ioctl_param *params,
+ 		     const uint32_t idx, struct param_value **value)
+ {
+@@ -336,7 +346,7 @@ static struct tee_shm *register_local_shm(int fd, size_t size)
+ 
+ 	memset(&data, 0, sizeof(data));
+ 
+-	buf = malloc(size);
++	buf = paged_aligned_alloc(size);
+ 	if (!buf)
+ 		return NULL;
+ 
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
new file mode 100644
index 0000000..d3b2319
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0001-core-SPMC-update-for-FF-A-version-1.0.patch
@@ -0,0 +1,50 @@
+Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/7c3b052b871420618a08402f626923fe85a139db]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 7c3b052b871420618a08402f626923fe85a139db Mon Sep 17 00:00:00 2001
+From: Marc Bonnici <marc.bonnici@arm.com>
+Date: Wed, 23 Sep 2020 13:55:22 +0100
+Subject: [PATCH 1/3] core: SPMC: update for FF-A version 1.0
+
+Update expected memory attributes. As per the FF-A spec (5.11.3)  a
+lender of a memory region should not specify the instruction access
+permission, therefore update the expected memory attribute.
+
+Updates the version number to 1.0 replacing the previous version number
+0.9.
+---
+ core/arch/arm/include/optee_ffa.h  | 4 ++--
+ core/arch/arm/kernel/thread_spmc.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h
+index 8498fbab..9daca732 100644
+--- a/core/arch/arm/include/optee_ffa.h
++++ b/core/arch/arm/include/optee_ffa.h
+@@ -27,8 +27,8 @@
+  * w3-w7: Implementation defined, free to be used below
+  */
+ 
+-#define OPTEE_FFA_VERSION_MAJOR	UINT32_C(0)
+-#define OPTEE_FFA_VERSION_MINOR	UINT32_C(9)
++#define OPTEE_FFA_VERSION_MAJOR	UINT32_C(1)
++#define OPTEE_FFA_VERSION_MINOR	UINT32_C(0)
+ 
+ #define OPTEE_FFA_BLOCKING_CALL(id)	UINT32_C(id)
+ #define OPTEE_FFA_YIELDING_CALL_BIT	31
+diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
+index 81edf03a..16f3bbe1 100644
+--- a/core/arch/arm/kernel/thread_spmc.c
++++ b/core/arch/arm/kernel/thread_spmc.c
+@@ -433,7 +433,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
+ {
+ 	struct mem_region_descr *region_descr = NULL;
+ 	struct mem_transaction_descr *descr = NULL;
+-	const uint8_t exp_mem_acc_perm = 0x6; /* Not executable, Read-write */
++	const uint8_t exp_mem_acc_perm = 0x2; /* Read-write */
+ 	/* Normal memory, Write-Back cacheable, Inner shareable */
+ 	const uint8_t exp_mem_reg_attr = 0x2f;
+ 	unsigned int num_mem_accs = 0;
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
new file mode 100644
index 0000000..32a420e
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0002-core-add-thread_smccc.patch
@@ -0,0 +1,89 @@
+Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/269e226eea2b2f26a6f844b7d25bc2b2a9b26315]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 269e226eea2b2f26a6f844b7d25bc2b2a9b26315 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Tue, 4 Feb 2020 17:30:55 +0100
+Subject: [PATCH 2/3] core: add thread_smccc()
+
+Adds the assembly function thread_smccc() which loads the first 8
+registers with the argument and executes an SMC or HVC instruction as
+appropriate. The result in the first 8 registers is then saved in the
+argument struct.
+
+Change-Id: Ie14154fb38de5ced3cfdebdb0bf19e48caaf2279
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+---
+ core/arch/arm/include/kernel/thread.h |  1 +
+ core/arch/arm/kernel/thread_a32.S     | 16 ++++++++++++++++
+ core/arch/arm/kernel/thread_a64.S     | 15 +++++++++++++++
+ 3 files changed, 32 insertions(+)
+
+diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
+index b9c0ba4b..4f0520e9 100644
+--- a/core/arch/arm/include/kernel/thread.h
++++ b/core/arch/arm/include/kernel/thread.h
+@@ -704,6 +704,7 @@ uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params,
+ 
+ unsigned long thread_smc(unsigned long func_id, unsigned long a1,
+ 			 unsigned long a2, unsigned long a3);
++void thread_smccc(struct thread_smc_args *arg_res);
+ 
+ /**
+  * Allocate data for payload buffers.
+diff --git a/core/arch/arm/kernel/thread_a32.S b/core/arch/arm/kernel/thread_a32.S
+index 199e90a9..75d85c32 100644
+--- a/core/arch/arm/kernel/thread_a32.S
++++ b/core/arch/arm/kernel/thread_a32.S
+@@ -210,6 +210,22 @@ FUNC thread_smc , :
+ 	bx	lr
+ END_FUNC thread_smc
+ 
++/* void thread_smccc(struct thread_smc_args *arg_res) */
++FUNC thread_smccc , :
++	push	{r4-r7}
++	push	{r0, lr}
++	ldm	r0, {r0-r7}
++#ifdef CFG_CORE_SEL2_SPMC
++	hvc	#0
++#else
++	smc	#0
++#endif
++	pop	{r12, lr}
++	stm	r12, {r0-r7}
++	pop	{r4-r7}
++	bx	lr
++END_FUNC thread_smccc
++
+ FUNC thread_init_vbar , :
+ 	/* Set vector (VBAR) */
+ 	write_vbar r0
+diff --git a/core/arch/arm/kernel/thread_a64.S b/core/arch/arm/kernel/thread_a64.S
+index 9ce31eb2..3e0f5115 100644
+--- a/core/arch/arm/kernel/thread_a64.S
++++ b/core/arch/arm/kernel/thread_a64.S
+@@ -65,6 +65,21 @@ FUNC thread_smc , :
+ 	ret
+ END_FUNC thread_smc
+ 
++/* void thread_smccc(struct thread_smc_args *arg_res) */
++FUNC thread_smccc , :
++	push	x0, xzr
++	mov	x8, x0
++	load_xregs x8, 0, 0, 7
++#ifdef CFG_CORE_SEL2_SPMC
++	hvc	#0
++#else
++	smc	#0
++#endif
++	pop	x8, xzr
++	store_xregs x8, 0, 0, 7
++	ret
++END_FUNC thread_smccc
++
+ FUNC thread_init_vbar , :
+ 	msr	vbar_el1, x0
+ 	ret
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
new file mode 100644
index 0000000..c3967dc
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch
@@ -0,0 +1,623 @@
+Upstream-Status: Pending [https://github.com/jenswi-linaro/optee_os/commit/80f0ec4ba2af33584e99e917fa165b77028a511f]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 80f0ec4ba2af33584e99e917fa165b77028a511f Mon Sep 17 00:00:00 2001
+From: Marc Bonnici <marc.bonnici@arm.com>
+Date: Fri, 5 Jun 2020 13:47:40 +0100
+Subject: [PATCH 3/3] core: enable SPCI with SPM Core at S-EL2
+
+This is a port of a pre-exisiting patch to support the case where
+the SPM Core is implementation at S-EL2, that is, in a secure hypervisor.
+This configuration is also know as "S-EL2 SPMC" in the FFA specification.
+
+Compile with CFG_CORE_SEL2_SPMC=y
+
+Note that this is an experimental feature, ABIs etc may have
+incompatible changes.
+
+Sqaushed in:
+	core: Update cookie to uint64 in S-EL2 code
+
+	As part of the update to FF-A 1.0 the globally
+	unique handle to identify a shared memory object is now 64
+	bits wide instead of 32. This commit updates the
+	remaining usage of 32 bit values.
+
+	core: Remove page count from S-EL2 code
+
+	The page count field has been dropped from upstream OP-TEE to
+	accommodate using a 64 bit handle in the same size message param struct,
+	therefore update our implementation to support this.
+
+	core: Update remaining FF-A structures to EAC
+
+	Update relinquish data structures and ABI invocations to the FFA
+	EAC spec
+---
+ core/arch/arm/arm.mk                   |   7 ++
+ core/arch/arm/include/kernel/thread.h  |   6 +
+ core/arch/arm/include/mm/mobj.h        |   6 +
+ core/arch/arm/kernel/thread_spmc.c     | 164 ++++++++++++++++++++++++-
+ core/arch/arm/kernel/thread_spmc_a64.S |   3 +-
+ core/arch/arm/mm/mobj_ffa.c            | 104 +++++++++++-----
+ core/arch/arm/plat-vexpress/conf.mk    |   5 +
+ 7 files changed, 260 insertions(+), 35 deletions(-)
+
+diff --git a/core/arch/arm/arm.mk b/core/arch/arm/arm.mk
+index f495f3c9..7c5e8fb0 100644
+--- a/core/arch/arm/arm.mk
++++ b/core/arch/arm/arm.mk
+@@ -97,6 +97,13 @@ endif
+ # changes
+ ifeq ($(CFG_CORE_SEL1_SPMC),y)
+ $(call force,CFG_CORE_FFA,y)
++$(call force,CFG_CORE_SEL2_SPMC,n)
++endif
++# SPMC configuration "S-EL2 SPMC" where SPM Core is implemented at S-EL2,
++# that is, the hypervisor sandboxing OP-TEE
++ifeq ($(CFG_CORE_SEL2_SPMC),y)
++$(call force,CFG_CORE_FFA,y)
++$(call force,CFG_CORE_SEL1_SPMC,n)
+ endif
+ 
+ # Unmaps all kernel mode code except the code needed to take exceptions
+diff --git a/core/arch/arm/include/kernel/thread.h b/core/arch/arm/include/kernel/thread.h
+index 4f0520e9..95f48589 100644
+--- a/core/arch/arm/include/kernel/thread.h
++++ b/core/arch/arm/include/kernel/thread.h
+@@ -759,6 +759,12 @@ enum thread_shm_cache_user {
+ void *thread_rpc_shm_cache_alloc(enum thread_shm_cache_user user,
+ 				 enum thread_shm_type shm_type,
+ 				 size_t size, struct mobj **mobj);
++
++#if defined(CFG_CORE_SEL2_SPMC)
++struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie);
++void thread_spmc_relinquish(uint64_t memory_region_handle);
++#endif
++
+ #endif /*__ASSEMBLER__*/
+ 
+ #endif /*KERNEL_THREAD_H*/
+diff --git a/core/arch/arm/include/mm/mobj.h b/core/arch/arm/include/mm/mobj.h
+index 2b9bd90c..3f820666 100644
+--- a/core/arch/arm/include/mm/mobj.h
++++ b/core/arch/arm/include/mm/mobj.h
+@@ -216,6 +216,12 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages);
+ void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj);
+ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie);
+ #endif
++#ifdef CFG_CORE_SEL2_SPMC
++struct mobj_ffa *mobj_ffa_sel2_spmc_new(uint64_t cookie,
++                                        unsigned int num_pages);
++void mobj_ffa_sel2_spmc_delete(struct mobj_ffa *mobj);
++#endif
++
+ uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj);
+ TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx,
+ 				 paddr_t pa, unsigned int num_pages);
+diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
+index 16f3bbe1..3d7dc035 100644
+--- a/core/arch/arm/kernel/thread_spmc.c
++++ b/core/arch/arm/kernel/thread_spmc.c
+@@ -7,6 +7,7 @@
+ #include <assert.h>
+ #include <ffa.h>
+ #include <io.h>
++#include <initcall.h>
+ #include <kernel/interrupt.h>
+ #include <kernel/panic.h>
+ #include <kernel/spinlock.h>
+@@ -88,6 +89,18 @@ struct mem_frag_state {
+ 
+ static uint16_t my_sp_id = 0x8001;
+ 
++
++/* Table 149: FFA_MEM_RELINQUISH. */
++struct ffa_relinquish_descriptor {
++       uint64_t handle;
++       uint32_t flags;
++       uint32_t endpoint_count;
++       uint16_t endpoint_id_array[];
++};
++
++/* Our VM ID is 0x8001, non-secure VM ID 0x0001 */
++const uint32_t thread_spmc_target_info = 0x80010001;
++
+ /*
+  * If @rxtx_size is 0 RX/TX buffers are not mapped or initialized.
+  *
+@@ -101,8 +114,16 @@ static uint16_t my_sp_id = 0x8001;
+  * these buffers so we must always be careful when reading. while we hold
+  * the lock.
+  */
++
++#ifdef CFG_CORE_SEL2_SPMC
++static uint8_t rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
++static uint8_t tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
++#else
+ static void *rx_buf;
+ static void *tx_buf;
++#endif
++
++
+ static unsigned int rxtx_size;
+ static unsigned int rxtx_spinlock;
+ static bool tx_buf_is_mine;
+@@ -127,6 +148,28 @@ static void set_args(struct thread_smc_args *args, uint32_t fid,
+ 					  .a5 = w5, };
+ }
+ 
++static int __maybe_unused
++set_pages(struct constituent_address_range *regions, unsigned int num_regions,
++	  unsigned int num_pages, struct mobj_ffa *mf)
++{
++	unsigned int n = 0;
++	unsigned int idx = 0;
++
++	for (n = 0; n < num_regions; n++) {
++		unsigned int page_count = READ_ONCE(regions[n].page_count);
++		uint64_t addr = READ_ONCE(regions[n].address);
++
++		if (mobj_ffa_add_pages_at(mf, &idx, addr, page_count))
++			return FFA_INVALID_PARAMETERS;
++	}
++
++	if (idx != num_pages)
++		return FFA_INVALID_PARAMETERS;
++
++	return 0;
++}
++
++
+ static void handle_version(struct thread_smc_args *args)
+ {
+ 	/*
+@@ -188,6 +231,7 @@ static void handle_features(struct thread_smc_args *args)
+ 		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+ }
+ 
++#ifdef CFG_CORE_SEL1_SPMC
+ static int map_buf(paddr_t pa, unsigned int sz, void **va_ret)
+ {
+ 	tee_mm_entry_t *mm = NULL;
+@@ -293,6 +337,7 @@ out:
+ 	set_args(args, ret_fid, FFA_PARAM_MBZ, rc,
+ 		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+ }
++#endif
+ 
+ static void handle_rx_release(struct thread_smc_args *args)
+ {
+@@ -408,6 +453,7 @@ static void handle_blocking_call(struct thread_smc_args *args)
+ 	}
+ }
+ 
++#if CFG_CORE_SEL1_SPMC
+ static int get_acc_perms(struct mem_accsess_descr *mem_acc,
+ 			 unsigned int num_mem_accs, uint8_t *acc_perms,
+ 			 unsigned int *region_offs)
+@@ -531,7 +577,11 @@ static int add_mem_share_frag(struct mem_frag_state *s, void *buf, size_t flen)
+ 
+ 	SLIST_REMOVE(&frag_state_head, s, mem_frag_state, link);
+ 	if (rc < 0)
++#ifdef CFG_CORE_SEL2_SPMC
++		mobj_ffa_sel2_spmc_delete(s->share.mf);
++#else
+ 		mobj_ffa_sel1_spmc_delete(s->share.mf);
++#endif
+ 	else
+ 		mobj_ffa_push_to_inactive(s->share.mf);
+ 	free(s);
+@@ -559,8 +609,8 @@ static int add_mem_share(tee_mm_entry_t *mm, void *buf, size_t blen,
+ 			 sizeof(struct constituent_address_range), &n) ||
+ 	    ADD_OVERFLOW(n, addr_range_offs, &n) || n > blen)
+ 		return FFA_INVALID_PARAMETERS;
+-
+ 	share.mf = mobj_ffa_sel1_spmc_new(share.page_count);
++
+ 	if (!share.mf)
+ 		return FFA_NO_MEMORY;
+ 
+@@ -601,6 +651,7 @@ static int add_mem_share(tee_mm_entry_t *mm, void *buf, size_t blen,
+ 	return 0;
+ err:
+ 	mobj_ffa_sel1_spmc_delete(share.mf);
++
+ 	return rc;
+ }
+ 
+@@ -809,6 +860,7 @@ static void handle_mem_reclaim(struct thread_smc_args *args)
+ out:
+ 	set_args(args, ret_fid, ret_val, 0, 0, 0, 0);
+ }
++#endif
+ 
+ /* Only called from assembly */
+ void thread_spmc_msg_recv(struct thread_smc_args *args);
+@@ -822,6 +874,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
+ 	case FFA_FEATURES:
+ 		handle_features(args);
+ 		break;
++#if CFG_CORE_SEL1_SPMC
+ #ifdef ARM64
+ 	case FFA_RXTX_MAP_64:
+ #endif
+@@ -831,6 +884,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
+ 	case FFA_RXTX_UNMAP:
+ 		handle_rxtx_unmap(args);
+ 		break;
++#endif
+ 	case FFA_RX_RELEASE:
+ 		handle_rx_release(args);
+ 		break;
+@@ -847,6 +901,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
+ 		else
+ 			handle_blocking_call(args);
+ 		break;
++#if CFG_CORE_SEL1_SPMC
+ #ifdef ARM64
+ 	case FFA_MEM_SHARE_64:
+ #endif
+@@ -859,6 +914,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
+ 	case FFA_MEM_FRAG_TX:
+ 		handle_mem_frag_tx(args);
+ 		break;
++#endif
+ 	default:
+ 		EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0);
+ 		set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED,
+@@ -1185,3 +1241,109 @@ void thread_rpc_free_global_payload(struct mobj *mobj __unused)
+ 
+ 	assert(!cant_happen);
+ }
++
++#ifdef CFG_CORE_SEL2_SPMC
++static void spmc_rxtx_map(void)
++{
++	struct thread_smc_args args = {
++		.a0 = FFA_RXTX_MAP_64,
++		.a1 = (vaddr_t)tx_buf,
++		.a2 = (vaddr_t)rx_buf,
++		.a3 = 1,
++	};
++
++	thread_smccc(&args);
++	if (args.a0 == FFA_ERROR) {
++		EMSG("ERROR rxtx map failed with error %ld\n", args.a2);
++		panic();
++	}
++}
++
++static struct mem_transaction_descr *spmc_retrieve_req(uint64_t cookie)
++{
++	struct mem_transaction_descr *retrieve_region = (void *)tx_buf;
++
++	struct thread_smc_args args = {
++		.a0 = FFA_MEM_RETRIEVE_REQ_64,
++		.a1 =   sizeof(*retrieve_region),  	// Total Length
++		.a2 =	sizeof(*retrieve_region),	// Frag Length == Total length
++		.a3 =	0,				// Address, Using TX -> MBZ
++		.a4 =   0 				// Using TX -> MBZ
++	};
++
++	/* TODO pass all the information required by the spec */
++	memset(retrieve_region, 0, sizeof(*retrieve_region));
++	retrieve_region->global_handle = cookie;
++
++	thread_smccc(&args);
++	if (args.a0 == FFA_ERROR /*TODO != FFA_MEM_RETRIEVE_RESP_64 */) {
++		EMSG("Failed to fetch cookie %#"PRIx64, cookie);
++		return NULL;
++	}
++
++	return (void *)rx_buf;
++}
++
++void thread_spmc_relinquish(uint64_t cookie)
++{
++	struct ffa_relinquish_descriptor *relinquish_desc = (void *)tx_buf;
++
++	struct thread_smc_args args = {
++		.a0 = FFA_MEM_RELINQUISH,
++	};
++
++	memset(relinquish_desc, 0, sizeof(*relinquish_desc));
++	relinquish_desc->handle = cookie;
++	relinquish_desc->flags = 0;
++	/* TODO: Add endpoint details. */
++	thread_smccc(&args);
++	if (args.a0 != FFA_SUCCESS_32)
++		EMSG("Failed to relinquish cookie %#"PRIx64, cookie);
++}
++
++struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
++{
++	struct mem_transaction_descr *retrieve_desc;
++	struct mem_region_descr *descr;
++	struct mobj_ffa *mf;
++	uint32_t num_pages;
++
++
++	/* XXX Support single mem_region. */
++	retrieve_desc = spmc_retrieve_req(cookie);
++
++	if (!retrieve_desc) {
++	    EMSG("Failed to retrieve cookie from rx buffer %#"PRIx64, cookie);
++	    return NULL;
++	}
++
++	descr = (struct mem_region_descr *)
++			((uint8_t *)retrieve_desc +
++				retrieve_desc->mem_accsess_descr_array[0].mem_region_offs);
++
++	num_pages = descr->total_page_count;
++	mf = mobj_ffa_sel2_spmc_new(cookie, num_pages);
++
++	if (!mf)
++		return NULL;
++
++	if (set_pages(descr->address_range_array,
++				  descr->address_range_count,
++				  num_pages, mf)) {
++		mobj_ffa_sel2_spmc_delete(mf);
++		return NULL;
++
++	}
++
++	return mf;
++}
++
++static TEE_Result spmc_init(void)
++{
++	spmc_rxtx_map();
++
++	return TEE_SUCCESS;
++}
++service_init(spmc_init);
++
++#endif /*CFG_CORE_SEL2_SPMC*/
+diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S
+index 3d57da4d..66f9d0b4 100644
+--- a/core/arch/arm/kernel/thread_spmc_a64.S
++++ b/core/arch/arm/kernel/thread_spmc_a64.S
+@@ -17,7 +17,8 @@
+ 
+ FUNC thread_ffa_msg_wait , :
+ 	mov_imm	x0, FFA_MSG_WAIT		/* FID */
+-	mov	x1, #FFA_TARGET_INFO_MBZ	/* Target info MBZ */
++	adr     x1, thread_spmc_target_info
++	ldr     w1, [x1]
+ 	mov	x2, #FFA_PARAM_MBZ		/* Param MBZ */
+ 	mov	x3, #FFA_PARAM_MBZ		/* Param MBZ */
+ 	mov	x4, #FFA_PARAM_MBZ		/* Param MBZ */
+diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
+index fd5e66ea..e2c585a2 100644
+--- a/core/arch/arm/mm/mobj_ffa.c
++++ b/core/arch/arm/mm/mobj_ffa.c
+@@ -19,8 +19,10 @@ struct mobj_ffa {
+ 	tee_mm_entry_t *mm;
+ 	struct refcount mapcount;
+ 	uint16_t page_offset;
++#ifdef CFG_CORE_SEL1_SPMC
+ 	bool registered_by_cookie;
+ 	bool unregistered_by_cookie;
++#endif
+ 	paddr_t pages[];
+ };
+ 
+@@ -186,6 +188,24 @@ void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf)
+ }
+ #endif /*CFG_CORE_SEL1_SPMC*/
+ 
++#ifdef CFG_CORE_SEL2_SPMC
++struct mobj_ffa *mobj_ffa_sel2_spmc_new(uint64_t cookie,
++					unsigned int num_pages)
++{
++	struct mobj_ffa *mf = NULL;
++
++	mf = ffa_new(num_pages);
++	if (mf)
++		mf->cookie = cookie;
++	return mf;
++}
++
++void mobj_ffa_sel2_spmc_delete(struct mobj_ffa *mf)
++{
++	free(mf);
++}
++#endif /*CFG_CORE_SEL2_SPMC*/
++
+ TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mf, unsigned int *idx,
+ 				 paddr_t pa, unsigned int num_pages)
+ {
+@@ -234,7 +254,9 @@ static void unmap_helper(struct mobj_ffa *mf)
+ 	}
+ }
+ 
+-TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
++
++#ifdef CFG_CORE_SEL1_SPMC
++TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
+ {
+ 	TEE_Result res = TEE_SUCCESS;
+ 	struct mobj_ffa *mf = NULL;
+@@ -244,7 +266,7 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
+ 	mf = find_in_list(&shm_head, cmp_cookie, cookie);
+ 	/*
+ 	 * If the mobj is found here it's still active and cannot be
+-	 * unregistered.
++	 * reclaimed.
+ 	 */
+ 	if (mf) {
+ 		DMSG("cookie %#"PRIx64" busy refc %u",
+@@ -252,24 +274,34 @@ TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
+ 		res = TEE_ERROR_BUSY;
+ 		goto out;
+ 	}
++
+ 	mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie);
++	if (!mf) {
++		res = TEE_ERROR_ITEM_NOT_FOUND;
++		goto out;
++	}
+ 	/*
+-	 * If the mobj isn't found or if it already has been unregistered.
++	 * If the mobj has been registered via mobj_ffa_get_by_cookie()
++	 * but not unregistered yet with mobj_ffa_unregister_by_cookie().
+ 	 */
+-	if (!mf || mf->unregistered_by_cookie) {
+-		res = TEE_ERROR_ITEM_NOT_FOUND;
++	if (mf->registered_by_cookie && !mf->unregistered_by_cookie) {
++		DMSG("cookie %#"PRIx64" busy", cookie);
++		res = TEE_ERROR_BUSY;
+ 		goto out;
+ 	}
+-	mf->unregistered_by_cookie = true;
+-	res = TEE_SUCCESS;
+ 
++	if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf))
++		panic();
++	res = TEE_SUCCESS;
+ out:
+ 	cpu_spin_unlock_xrestore(&shm_lock, exceptions);
++	if (!res)
++		mobj_ffa_sel1_spmc_delete(mf);
+ 	return res;
+ }
++#endif /*CFG_CORE_SEL1_SPMC*/
+ 
+-#ifdef CFG_CORE_SEL1_SPMC
+-TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
++TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie)
+ {
+ 	TEE_Result res = TEE_SUCCESS;
+ 	struct mobj_ffa *mf = NULL;
+@@ -279,7 +311,7 @@ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
+ 	mf = find_in_list(&shm_head, cmp_cookie, cookie);
+ 	/*
+ 	 * If the mobj is found here it's still active and cannot be
+-	 * reclaimed.
++	 * unregistered.
+ 	 */
+ 	if (mf) {
+ 		DMSG("cookie %#"PRIx64" busy refc %u",
+@@ -287,43 +319,42 @@ TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie)
+ 		res = TEE_ERROR_BUSY;
+ 		goto out;
+ 	}
+-
+ 	mf = find_in_list(&shm_inactive_head, cmp_cookie, cookie);
+-	if (!mf) {
+-		res = TEE_ERROR_ITEM_NOT_FOUND;
+-		goto out;
+-	}
+ 	/*
+-	 * If the mobj has been registered via mobj_ffa_get_by_cookie()
+-	 * but not unregistered yet with mobj_ffa_unregister_by_cookie().
++	 * If the mobj isn't found or if it already has been unregistered.
+ 	 */
+-	if (mf->registered_by_cookie && !mf->unregistered_by_cookie) {
+-		DMSG("cookie %#"PRIx64" busy", cookie);
+-		res = TEE_ERROR_BUSY;
++#ifdef CFG_CORE_SEL2_SPMC
++	if (!mf) {
++#else
++	if (!mf || mf->unregistered_by_cookie) {
++#endif
++		res = TEE_ERROR_ITEM_NOT_FOUND;
+ 		goto out;
+ 	}
+ 
+-	if (!pop_from_list(&shm_inactive_head, cmp_ptr, (vaddr_t)mf))
+-		panic();
++
++#ifdef CFG_CORE_SEL2_SPMC
++	mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie);
++	mobj_ffa_sel2_spmc_delete(mf);
++	thread_spmc_relinquish(cookie);
++#else
++	mf->unregistered_by_cookie = true;
++#endif
+ 	res = TEE_SUCCESS;
++
+ out:
+ 	cpu_spin_unlock_xrestore(&shm_lock, exceptions);
+-	if (!res)
+-		mobj_ffa_sel1_spmc_delete(mf);
+ 	return res;
+ }
+-#endif /*CFG_CORE_SEL1_SPMC*/
+ 
+-struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
++struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
++				    unsigned int internal_offs)
+ {
+ 	struct mobj_ffa *mf = NULL;
+ 	uint32_t exceptions = 0;
+-
+ 	if (internal_offs >= SMALL_PAGE_SIZE)
+ 		return NULL;
+-
+ 	exceptions = cpu_spin_lock_xsave(&shm_lock);
+-
+ 	mf = find_in_list(&shm_head, cmp_cookie, cookie);
+ 	if (mf) {
+ 		if (mf->page_offset == internal_offs) {
+@@ -345,9 +376,19 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
+ 		}
+ 	} else {
+ 		mf = pop_from_list(&shm_inactive_head, cmp_cookie, cookie);
++#if defined(CFG_CORE_SEL2_SPMC)
++		/* Try to retrieve it from the SPM at S-EL2 */
++		if (mf)
++			DMSG("cookie %#"PRIx64" resurrecting", cookie);
++		if (!mf)
++			EMSG("Populating mobj from rx buffer\n");
++			mf = thread_spmc_populate_mobj_from_rx(cookie);
++#endif
+ 		if (mf) {
++#if defined(CFG_CORE_SEL1_SPMC)
+ 			mf->unregistered_by_cookie = false;
+ 			mf->registered_by_cookie = true;
++#endif
+ 			assert(refcount_val(&mf->mobj.refc) == 0);
+ 			refcount_set(&mf->mobj.refc, 1);
+ 			refcount_set(&mf->mapcount, 0);
+@@ -358,15 +399,12 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie, unsigned int internal_offs)
+ 			SLIST_INSERT_HEAD(&shm_head, mf, link);
+ 		}
+ 	}
+-
+ 	cpu_spin_unlock_xrestore(&shm_lock, exceptions);
+-
+ 	if (!mf) {
+ 		EMSG("Failed to get cookie %#"PRIx64" internal_offs %#x",
+-		     cookie, internal_offs);
++			cookie, internal_offs);
+ 		return NULL;
+ 	}
+-
+ 	return &mf->mobj;
+ }
+ 
+diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk
+index 26b9f51e..dd6530a6 100644
+--- a/core/arch/arm/plat-vexpress/conf.mk
++++ b/core/arch/arm/plat-vexpress/conf.mk
+@@ -58,8 +58,13 @@ CFG_WITH_STATS ?= y
+ 
+ ifeq ($(PLATFORM_FLAVOR),fvp)
+ CFG_TEE_CORE_NB_CORE = 8
++ifeq ($(CFG_CORE_SEL2_SPMC),y)
++CFG_TZDRAM_START ?= 0x06280000
++CFG_TZDRAM_SIZE  ?= 0x01D80000
++else
+ CFG_TZDRAM_START ?= 0x06000000
+ CFG_TZDRAM_SIZE  ?= 0x02000000
++endif
+ CFG_SHMEM_START  ?= 0x83000000
+ CFG_SHMEM_SIZE   ?= 0x00200000
+ # DRAM1 is defined above 4G
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
new file mode 100644
index 0000000..a36a510
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0004-core-fixes-to-align-with-upstream-hafnium.patch
@@ -0,0 +1,188 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 5ca96d9ff7fa5481282fb8f59a54d3cc91a1ae36 Mon Sep 17 00:00:00 2001
+From: Olivier Deprez <olivier.deprez@arm.com>
+Date: Thu, 1 Oct 2020 07:59:54 +0200
+Subject: [PATCH 1/5] core: fixes to align with upstream hafnium
+
+FF-A: fix call to thread_spmc_populate_mobj_from_rx
+
+FF-A: fix typos in thread_spmc.c
+
+FF-A: fix mem retrieve request
+
+FF-A. fix mem relinquish
+
+FF-A: call rx release from thread_spmc_populate_mobj_from_rx
+
+Change-Id: I38794b34bf17428d62218e30bdd0180f75498ed4
+Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ core/arch/arm/kernel/thread_spmc.c | 52 +++++++++++++++++++++---------
+ core/arch/arm/mm/mobj_ffa.c        |  3 +-
+ 2 files changed, 39 insertions(+), 16 deletions(-)
+
+diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
+index 3d7dc035..872221d6 100644
+--- a/core/arch/arm/kernel/thread_spmc.c
++++ b/core/arch/arm/kernel/thread_spmc.c
+@@ -48,7 +48,7 @@ struct mem_access_perm_descr {
+ };
+ 
+ /* Table 41: Endpoint memory access descriptor */
+-struct mem_accsess_descr {
++struct mem_access_descr {
+ 	struct mem_access_perm_descr mem_access_perm_descr;
+ 	uint32_t mem_region_offs;
+ 	uint64_t reserved;
+@@ -64,7 +64,7 @@ struct mem_transaction_descr {
+ 	uint64_t tag;
+ 	uint32_t reserved1;
+ 	uint32_t mem_access_descr_count;
+-	struct mem_accsess_descr mem_accsess_descr_array[];
++	struct mem_access_descr mem_access_descr_array[];
+ };
+ 
+ struct ffa_partition_info {
+@@ -453,8 +453,8 @@ static void handle_blocking_call(struct thread_smc_args *args)
+ 	}
+ }
+ 
+-#if CFG_CORE_SEL1_SPMC
+-static int get_acc_perms(struct mem_accsess_descr *mem_acc,
++#ifdef CFG_CORE_SEL1_SPMC
++static int get_acc_perms(struct mem_access_descr *mem_acc,
+ 			 unsigned int num_mem_accs, uint8_t *acc_perms,
+ 			 unsigned int *region_offs)
+ {
+@@ -495,7 +495,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
+ 
+ 	/* Check that the endpoint memory access descriptor array fits */
+ 	num_mem_accs = READ_ONCE(descr->mem_access_descr_count);
+-	if (MUL_OVERFLOW(sizeof(struct mem_accsess_descr), num_mem_accs, &n) ||
++	if (MUL_OVERFLOW(sizeof(struct mem_access_descr), num_mem_accs, &n) ||
+ 	    ADD_OVERFLOW(sizeof(*descr), n, &n) || n > blen)
+ 		return FFA_INVALID_PARAMETERS;
+ 
+@@ -503,7 +503,7 @@ static int mem_share_init(void *buf, size_t blen, unsigned int *page_count,
+ 		return FFA_INVALID_PARAMETERS;
+ 
+ 	/* Check that the access permissions matches what's expected */
+-	if (get_acc_perms(descr->mem_accsess_descr_array,
++	if (get_acc_perms(descr->mem_access_descr_array,
+ 			  num_mem_accs, &mem_acc_perm, &region_descr_offs) ||
+ 	    mem_acc_perm != exp_mem_acc_perm)
+ 		return FFA_INVALID_PARAMETERS;
+@@ -1263,17 +1263,29 @@ static struct mem_transaction_descr *spmc_retrieve_req(uint64_t cookie)
+ {
+ 	struct mem_transaction_descr *retrieve_region = (void *)tx_buf;
+ 
++	uint64_t size = sizeof(*retrieve_region) +
++		1 * sizeof(struct mem_access_descr);
+ 	struct thread_smc_args args = {
+ 		.a0 = FFA_MEM_RETRIEVE_REQ_64,
+-		.a1 =   sizeof(*retrieve_region),  	// Total Length
+-		.a2 =	sizeof(*retrieve_region),	// Frag Length == Total length
++		.a1 =   size,  	// Total Length
++		.a2 =	size,	// Frag Length == Total length
+ 		.a3 =	0,				// Address, Using TX -> MBZ
+ 		.a4 =   0 				// Using TX -> MBZ
+ 	};
+ 
+ 	/* TODO pass all the information required by the spec */
+-	memset(retrieve_region, 0, sizeof(*retrieve_region));
++	memset(retrieve_region, 0, size);
+ 	retrieve_region->global_handle = cookie;
++	retrieve_region->flags = 1;
++	retrieve_region->mem_access_descr_count = 1;
++	retrieve_region->mem_access_descr_array[0].mem_region_offs = 0;
++	retrieve_region->mem_access_descr_array[0].reserved = 0;
++	retrieve_region->mem_access_descr_array[0].mem_access_perm_descr =
++		(struct mem_access_perm_descr) {
++			.endpoint_id = my_sp_id,
++			.access_perm = 0,
++			.flags = 0
++		};
+ 
+ 	thread_smccc(&args);
+ 	if (args.a0 == FFA_ERROR /*TODO != FFA_MEM_RETRIEVE_RESP_64 */) {
+@@ -1296,6 +1308,8 @@ void thread_spmc_relinquish(uint64_t cookie)
+ 	relinquish_desc->handle = cookie;
+ 	relinquish_desc->flags = 0;
+ 	/* TODO: Add endpoint details. */
++	relinquish_desc->endpoint_count = 1;
++	relinquish_desc->endpoint_id_array[0] = my_sp_id;
+ 	thread_smccc(&args);
+ 	if (args.a0 != FFA_SUCCESS_32)
+ 		EMSG("Failed to relinquish cookie %#"PRIx64, cookie);
+@@ -1303,11 +1317,14 @@ void thread_spmc_relinquish(uint64_t cookie)
+ 
+ struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
+ {
++	struct mobj_ffa *ret = NULL;
+ 	struct mem_transaction_descr *retrieve_desc;
+ 	struct mem_region_descr *descr;
+ 	struct mobj_ffa *mf;
+ 	uint32_t num_pages;
+-
++	struct thread_smc_args ffa_rx_release_args = {
++		.a0 = FFA_RX_RELEASE
++	};
+ 
+ 	/* XXX Support single mem_region. */
+ 	retrieve_desc = spmc_retrieve_req(cookie);
+@@ -1319,23 +1336,28 @@ struct mobj_ffa *thread_spmc_populate_mobj_from_rx(uint64_t cookie)
+ 
+ 	descr = (struct mem_region_descr *)
+ 			((uint8_t *)retrieve_desc +
+-				retrieve_desc->mem_accsess_descr_array[0].mem_region_offs);
++				retrieve_desc->mem_access_descr_array[0].mem_region_offs);
+ 
+ 	num_pages = descr->total_page_count;
+ 	mf = mobj_ffa_sel2_spmc_new(cookie, num_pages);
+ 
+ 	if (!mf)
+-		return NULL;
++		goto out;
+ 
+ 	if (set_pages(descr->address_range_array,
+ 				  descr->address_range_count,
+ 				  num_pages, mf)) {
+ 		mobj_ffa_sel2_spmc_delete(mf);
+-		return NULL;
+-
++		goto out;
+ 	}
+ 
+-	return mf;
++	ret = mf;
++
++out:
++	/* Release RX buffer after the mem retrieve request. */
++	thread_smccc(&ffa_rx_release_args);
++
++	return ret;
+ }
+ 
+ static TEE_Result spmc_init(void)
+diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
+index e2c585a2..8e334f04 100644
+--- a/core/arch/arm/mm/mobj_ffa.c
++++ b/core/arch/arm/mm/mobj_ffa.c
+@@ -380,9 +380,10 @@ struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
+ 		/* Try to retrieve it from the SPM at S-EL2 */
+ 		if (mf)
+ 			DMSG("cookie %#"PRIx64" resurrecting", cookie);
+-		if (!mf)
++		if (!mf) {
+ 			EMSG("Populating mobj from rx buffer\n");
+ 			mf = thread_spmc_populate_mobj_from_rx(cookie);
++		}
+ #endif
+ 		if (mf) {
+ #if defined(CFG_CORE_SEL1_SPMC)
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
new file mode 100644
index 0000000..52270ec
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0005-core-arm-Total-Compute-platform-support.patch
@@ -0,0 +1,187 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 0c427d7f164a46862f6267b616d4ade28865b57a Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Wed, 15 Jul 2020 12:51:04 +0100
+Subject: [PATCH 2/5] core: arm: Total Compute platform support
+
+Initial support for Total Compute platform[1]
+    - defines tc0 platform configuration
+    - enables CFG_ARM64_core by default
+    - defines TZCDRAM_BASE
+
+Link: [1] https://community.arm.com/developer/tools-software/oss-platforms/w/docs/606/total-compute
+
+Change-Id: Icddafbdfac40bb6ff3c367910acf632688343721
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ core/arch/arm/plat-totalcompute/conf.mk       | 32 +++++++++++
+ core/arch/arm/plat-totalcompute/main.c        | 55 +++++++++++++++++++
+ .../arm/plat-totalcompute/platform_config.h   | 43 +++++++++++++++
+ core/arch/arm/plat-totalcompute/sub.mk        |  2 +
+ 4 files changed, 132 insertions(+)
+ create mode 100644 core/arch/arm/plat-totalcompute/conf.mk
+ create mode 100644 core/arch/arm/plat-totalcompute/main.c
+ create mode 100644 core/arch/arm/plat-totalcompute/platform_config.h
+ create mode 100644 core/arch/arm/plat-totalcompute/sub.mk
+
+diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
+new file mode 100644
+index 00000000..4fe894c7
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/conf.mk
+@@ -0,0 +1,32 @@
++PLATFORM_FLAVOR ?= tc0
++
++ifeq ($(PLATFORM_FLAVOR),tc0)
++include core/arch/arm/cpu/cortex-armv8-0.mk
++platform-debugger-arm := 1
++endif
++
++$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
++$(call force,CFG_GENERIC_BOOT,y)
++$(call force,CFG_GIC,y)
++$(call force,CFG_ARM_GICV3,y)
++$(call force,CFG_PL011,y)
++$(call force,CFG_PM_STUBS,y)
++$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
++$(call force,CFG_ARM64_core,y)
++$(call force,CFG_WITH_LPAE,y)
++
++ifeq ($(platform-debugger-arm),1)
++# ARM debugger needs this
++platform-cflags-debug-info = -gdwarf-2
++platform-aflags-debug-info = -gdwarf-2
++endif
++
++ifeq ($(PLATFORM_FLAVOR),tc0)
++CFG_TEE_CORE_NB_CORE = 4
++
++CFG_TZDRAM_START ?= 0xff000000
++CFG_TZDRAM_SIZE  ?= 0x01000000
++
++CFG_SHMEM_START  ?= 0xfce00000
++CFG_SHMEM_SIZE   ?= 0x00200000
++endif
+diff --git a/core/arch/arm/plat-totalcompute/main.c b/core/arch/arm/plat-totalcompute/main.c
+new file mode 100644
+index 00000000..e775abfc
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/main.c
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (c) 2020, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <arm.h>
++#include <console.h>
++#include <drivers/gic.h>
++#include <drivers/pl011.h>
++#include <initcall.h>
++#include <kernel/boot.h>
++#include <kernel/interrupt.h>
++#include <kernel/misc.h>
++#include <kernel/panic.h>
++
++#include <mm/core_mmu.h>
++#include <platform_config.h>
++
++static struct gic_data gic_data __nex_bss;
++static struct pl011_data console_data __nex_bss;
++
++register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
++register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
++
++register_ddr(DRAM0_BASE, DRAM0_SIZE);
++
++void main_init_gic(void)
++{
++	vaddr_t gicc_base;
++
++	gicc_base = (vaddr_t)phys_to_virt(GIC_BASE + GICC_OFFSET,
++					  MEM_AREA_IO_SEC);
++	if (!gicc_base)
++		panic();
++
++	/*
++	 * On ARMv8, GIC configuration is initialized in ARM-TF
++	 * gicd base address is same as gicc_base.
++	 */
++	gic_init_base_addr(&gic_data, gicc_base, gicc_base);
++	itr_init(&gic_data.chip);
++}
++
++void itr_core_handler(void)
++{
++	gic_it_handle(&gic_data);
++}
++
++void console_init(void)
++{
++	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
++		   CONSOLE_UART_BAUDRATE);
++	register_serial_console(&console_data.chip);
++}
+diff --git a/core/arch/arm/plat-totalcompute/platform_config.h b/core/arch/arm/plat-totalcompute/platform_config.h
+new file mode 100644
+index 00000000..dfc58857
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/platform_config.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (c) 2020, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PLATFORM_CONFIG_H
++#define PLATFORM_CONFIG_H
++
++#include <mm/generic_ram_layout.h>
++
++/* Make stacks aligned to data cache line length */
++#define STACK_ALIGNMENT		64
++
++#if defined(PLATFORM_FLAVOR_tc0)
++#define GIC_BASE		0x30000000
++#define GICD_OFFSET		0x0
++#define GICC_OFFSET		0x0
++
++#define UART0_BASE		0x7FF70000
++#define UART1_BASE		0x7FF80000
++
++#define CONSOLE_UART_BASE	UART0_BASE
++
++#define DRAM0_BASE		0x80000000
++#define DRAM0_SIZE		0x7d000000
++
++#define TZCDRAM_BASE		0xff000000
++#define TZCDRAM_SIZE		0x01000000
++
++#else
++#error "Unknown platform flavor"
++#endif
++
++#ifdef GIC_BASE
++#define GICD_BASE		(GIC_BASE + GICD_OFFSET)
++#define GICC_BASE		(GIC_BASE + GICC_OFFSET)
++#endif
++
++#define CONSOLE_UART_BAUDRATE	115200
++#define CONSOLE_UART_CLK_IN_HZ	7372800
++
++#endif /* PLATFORM_CONFIG_H */
+diff --git a/core/arch/arm/plat-totalcompute/sub.mk b/core/arch/arm/plat-totalcompute/sub.mk
+new file mode 100644
+index 00000000..8ddc2fd4
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/sub.mk
+@@ -0,0 +1,2 @@
++global-incdirs-y += .
++srcs-y += main.c
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
new file mode 100644
index 0000000..3070d5f
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch
@@ -0,0 +1,108 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 8c21a8c7ac92839f36f83ebff9a208f24302c780 Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Mon, 16 Nov 2020 17:29:09 +0000
+Subject: [PATCH 3/5] plat-totalcompute: Add support for S-EL2 SPMC
+
+This patch adds CFG_CORE_SEL2_SPMC support. Defines CFG_TZDRAM_START
+address with memory region reserved for SPMC. Adds secondary cpu boot
+request handler.
+
+Change-Id: I3f274c7bb6b7df2706ea81aee0f2a8f8f39c1d80
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ core/arch/arm/plat-totalcompute/conf.mk       |  5 ++
+ core/arch/arm/plat-totalcompute/sub.mk        |  3 ++
+ core/arch/arm/plat-totalcompute/tc0_spmc_pm.c | 50 +++++++++++++++++++
+ 3 files changed, 58 insertions(+)
+ create mode 100644 core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
+
+diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
+index 4fe894c7..34095acf 100644
+--- a/core/arch/arm/plat-totalcompute/conf.mk
++++ b/core/arch/arm/plat-totalcompute/conf.mk
+@@ -24,8 +24,13 @@ endif
+ ifeq ($(PLATFORM_FLAVOR),tc0)
+ CFG_TEE_CORE_NB_CORE = 4
+ 
++ifeq ($(CFG_CORE_SEL2_SPMC),y)
++CFG_TZDRAM_START ?= 0xfd281000
++CFG_TZDRAM_SIZE  ?= 0x01d7f000
++else
+ CFG_TZDRAM_START ?= 0xff000000
+ CFG_TZDRAM_SIZE  ?= 0x01000000
++endif
+ 
+ CFG_SHMEM_START  ?= 0xfce00000
+ CFG_SHMEM_SIZE   ?= 0x00200000
+diff --git a/core/arch/arm/plat-totalcompute/sub.mk b/core/arch/arm/plat-totalcompute/sub.mk
+index 8ddc2fd4..ffd76ee9 100644
+--- a/core/arch/arm/plat-totalcompute/sub.mk
++++ b/core/arch/arm/plat-totalcompute/sub.mk
+@@ -1,2 +1,5 @@
+ global-incdirs-y += .
+ srcs-y += main.c
++ifeq ($(CFG_CORE_FFA),y)
++srcs-y += tc0_spmc_pm.c
++endif
+diff --git a/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
+new file mode 100644
+index 00000000..8e59a8cc
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/tc0_spmc_pm.c
+@@ -0,0 +1,50 @@
++// SPDX-License-Identifier: BSD-2-Clause
++/*
++ * Copyright (c) 2020, Arm Limited
++ */
++
++#include <arm.h>
++#include <kernel/boot.h>
++#include <ffa.h>
++#include <sm/psci.h>
++
++/*
++ * Lookup table of core and cluster affinities on the TC0. In the absence of a
++ * DT that provides the same information, this table is used to initialise
++ * OP-TEE on secondary cores.
++ */
++static const uint64_t core_clus_aff_array[] = {
++	0x0000,		/* Cluster 0 Cpu 0 */
++	0x0001,		/* Cluster 0 Cpu 1 */
++	0x0002,		/* Cluster 0 Cpu 2 */
++	0x0003		/* Cluster 0 Cpu 3 */
++};
++
++void ffa_secondary_cpu_boot_req(vaddr_t secondary_ep, uint64_t cookie)
++{
++	unsigned long mpidr = read_mpidr();
++	unsigned int aff_shift = 0;
++	unsigned long a1 = 0;
++	unsigned int cnt = 0;
++	int32_t ret = 0;
++
++	if (mpidr & MPIDR_MT_MASK)
++		aff_shift = MPIDR_CLUSTER_SHIFT;
++
++	for (cnt = 0; cnt < ARRAY_SIZE(core_clus_aff_array); cnt++) {
++		/* Clear out the affinity fields until level 2 */
++		a1 = mpidr & ~(unsigned long)MPIDR_AARCH32_AFF_MASK;
++
++		/* Create an mpidr from core_clus_aff_array */
++		a1 |= core_clus_aff_array[cnt] << aff_shift;
++
++		/* Invoke the PSCI_CPU_ON_SMC64 function */
++		ret = thread_smc(PSCI_CPU_ON_SMC64, a1, secondary_ep, cookie);
++
++		if (ret != PSCI_RET_SUCCESS)
++			EMSG("PSCI_CPU_ON op on mpidr 0x%lx failed %"PRId32,
++			     a1, ret);
++		else
++			DMSG("PSCI_CPU_ON op on mpidr 0x%lx done", a1);
++	}
++}
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
new file mode 100644
index 0000000..6535496
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch
@@ -0,0 +1,73 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 582bf63102ec37dadff2147dcebcb62783dcf377 Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Mon, 16 Nov 2020 18:03:21 +0000
+Subject: [PATCH 4/5] plat-totalcompute: add optee manifest file and sp layout
+
+For S-EL2 SPMC, add optee manifest file and sp layout file
+
+Change-Id: Ic3179987decf4e017cd4a0ad91b3beeea2bd6ca1
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ .../arm/plat-totalcompute/optee_manifest.dts  | 33 +++++++++++++++++++
+ .../arch/arm/plat-totalcompute/sp_layout.json |  6 ++++
+ 2 files changed, 39 insertions(+)
+ create mode 100644 core/arch/arm/plat-totalcompute/optee_manifest.dts
+ create mode 100644 core/arch/arm/plat-totalcompute/sp_layout.json
+
+diff --git a/core/arch/arm/plat-totalcompute/optee_manifest.dts b/core/arch/arm/plat-totalcompute/optee_manifest.dts
+new file mode 100644
+index 00000000..4e60cbe1
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/optee_manifest.dts
+@@ -0,0 +1,33 @@
++/*
++ * Copyright (c) 2020, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ * This file is a Partition Manifest (PM) for a minimal Secure Partition (SP)
++ * that has additional optional properties defined.
++ *
++ */
++
++/dts-v1/;
++
++/ {
++	compatible = "arm,ffa-manifest-1.0";
++
++	/* Properties */
++	description = "op-tee";
++	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
++	uuid = <0x486178e0 0xe7f811e3 0xbc5e0002 0xa5d5c51b>;
++	id = <1>;
++	execution-ctx-count = <4>;
++	exception-level = <2>; /* S-EL1 */
++	execution-state = <0>; /* AARCH64 */
++	load-address = <0xfd280000>;
++	entrypoint-offset = <0x1000>;
++	xlat-granule = <0>; /* 4KiB */
++	boot-order = <0>;
++	messaging-method = <0>; /* Direct messaging only */
++	run-time-model = <1>; /* Run to completion */
++
++	/* Boot protocol */
++	gp-register-num = <0x0>;
++};
+diff --git a/core/arch/arm/plat-totalcompute/sp_layout.json b/core/arch/arm/plat-totalcompute/sp_layout.json
+new file mode 100644
+index 00000000..05bc7851
+--- /dev/null
++++ b/core/arch/arm/plat-totalcompute/sp_layout.json
+@@ -0,0 +1,6 @@
++{
++	"op-tee" : {
++		"image": "tee-pager_v2.bin",
++		"pm": "optee_manifest.dts"
++	}
++}
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch
new file mode 100644
index 0000000..015bdc9
--- /dev/null
+++ b/meta-arm-bsp/recipes-security/optee/files/optee-os/tc0/0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch
@@ -0,0 +1,36 @@
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 1827607c6381339d051a36a84d749c3a50e3463d Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Mon, 16 Nov 2020 17:38:07 +0000
+Subject: [PATCH 5/5] plat-totalcompute: define tzdram start address for S-EL1
+ SPMC config
+
+Define TZDRAM_START for CFG_CORE_SEL1_SPMC config
+
+Change-Id: I71aaa92a0ecdb791802336ca31ab52e97ee52955
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ core/arch/arm/plat-totalcompute/conf.mk | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/core/arch/arm/plat-totalcompute/conf.mk b/core/arch/arm/plat-totalcompute/conf.mk
+index 34095acf..d330eb92 100644
+--- a/core/arch/arm/plat-totalcompute/conf.mk
++++ b/core/arch/arm/plat-totalcompute/conf.mk
+@@ -24,7 +24,10 @@ endif
+ ifeq ($(PLATFORM_FLAVOR),tc0)
+ CFG_TEE_CORE_NB_CORE = 4
+ 
+-ifeq ($(CFG_CORE_SEL2_SPMC),y)
++ifeq ($(CFG_CORE_SEL1_SPMC),y)
++CFG_TZDRAM_START ?= 0xfd000000
++CFG_TZDRAM_SIZE  ?= 0x02000000
++else ifeq ($(CFG_CORE_SEL2_SPMC),y)
+ CFG_TZDRAM_START ?= 0xfd281000
+ CFG_TZDRAM_SIZE  ?= 0x01d7f000
+ else
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
index 8b13386..ad9c475 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-client-tc0.inc
@@ -3,3 +3,10 @@
 # Intermediate SHA with 3.11 baseline version
 SRCREV = "3f44b870299514ad8c6b7dee776eb2994d9c1cd4"
 PV = "3.11.0+git${SRCPV}"
+
+FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/optee-client/tc0:"
+
+SRC_URI_append = " \
+    file://0001-Revert-libteec-Avoid-memcpy-when-using-TEEC_TempMemo.patch \
+    file://0002-Allocate-page-aligned-shared-memory-buffers.patch \
+    "
diff --git a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
index a700daf..fc89a9f 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
@@ -9,7 +9,20 @@ SRC_URI_remove = " \
     file://0001-libutils-provide-empty-__getauxval-implementation.patch \
     file://0002-link.mk-implement-support-for-libnames-after-libgcc-.patch \
     file://0003-ta_dev_kit.mk-make-sure-that-libutils-is-linked-seco.patch \
-"
+    "
+
+FILESEXTRAPATHS_prepend_tc0 := "${THISDIR}/files/optee-os/tc0:"
+
+SRC_URI_append = " \
+    file://0001-core-SPMC-update-for-FF-A-version-1.0.patch \
+    file://0002-core-add-thread_smccc.patch \
+    file://0003-core-enable-SPCI-with-SPM-Core-at-S-EL2.patch \
+    file://0004-core-fixes-to-align-with-upstream-hafnium.patch \
+    file://0005-core-arm-Total-Compute-platform-support.patch \
+    file://0006-plat-totalcompute-Add-support-for-S-EL2-SPMC.patch \
+    file://0007-plat-totalcompute-add-optee-manifest-file-and-sp-lay.patch \
+    file://0008-plat-totalcompute-define-tzdram-start-address-for-S-.patch \
+    "
 
 COMPATIBLE_MACHINE = "tc0"
 
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 06/10] arm-bsp/tc0: Enable optee core with SPMC at SEL2
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (3 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 05/10] arm-bsp/tc0: Add tc0 platform support patches " Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 07/10] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

Sets config flag CFG_CORE_SEL2_SPMC. Copies optee manifest file and
sp_layout files to deploy directory.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: If2104e2d588cbc9fbd9db3d8c4ba9fb74732901b
---
 .../recipes-security/optee/optee-os-tc0.inc   | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
index fc89a9f..fff6381 100644
--- a/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
+++ b/meta-arm-bsp/recipes-security/optee/optee-os-tc0.inc
@@ -27,3 +27,25 @@ SRC_URI_append = " \
 COMPATIBLE_MACHINE = "tc0"
 
 OPTEEMACHINE = "totalcompute-tc0"
+
+# Enable optee memory layout and boot logs
+EXTRA_OEMAKE += " CFG_TEE_CORE_LOG_LEVEL=3"
+
+# default disable latency benchmarks (over all OP-TEE layers)
+EXTRA_OEMAKE += " CFG_TEE_BENCHMARK=n"
+
+# Enable stats
+EXTRA_OEMAKE += " CFG_WITH_STATS=y"
+
+EXTRA_OEMAKE += " CFG_CORE_SEL2_SPMC=y"
+
+# Copy optee manifest file and sp_layout
+# This function will be modified or removed once upstream optee-os adds support
+# for SEL2 SPMC config
+do_install_append() {
+    install -d ${D}${nonarch_base_libdir}/firmware/
+    install -m 644 ${S}/core/arch/arm/plat-totalcompute/sp_layout.json \
+        ${D}${nonarch_base_libdir}/firmware/
+    install -m 644 ${S}/core/arch/arm/plat-totalcompute/optee_manifest.dts \
+        ${D}${nonarch_base_libdir}/firmware/
+}
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 07/10] arm-bsp/linux: add ffa driver to TC0
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (4 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 06/10] arm-bsp/tc0: Enable optee core with SPMC at SEL2 Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 08/10] arm-bsp/linux: enable ffa driver for TC0 Arunachalam Ganapathy
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

This patch contains initial version of ffa driver adopted for
android11-5.4-lts kernel.

This is based on prototype ffa driver released by Arm.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: Idb198cc77368a95257f1b5bff37b17bd13144109
---
 .../linux/linux-arm-platforms.inc             |    1 +
 ...Initial-version-of-ffa-driver-based-.patch | 1461 +++++++++++++++++
 2 files changed, 1462 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch

diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
index 1c9fdc1..873f120 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
@@ -76,6 +76,7 @@ SRC_URI_append_tc0 = " \
     file://0006-mailbox-arm_mhuv2-add-multi-word-transport-protocol-.patch \
     file://0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch \
     file://0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch \
+    file://0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch \
     "
 
 #
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch
new file mode 100644
index 0000000..e5e1ff6
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch
@@ -0,0 +1,1461 @@
+Upstream-Status: Pending [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=ffa_rel_proto&id=74aeede25bd737f4930e1322f5780ec1c61b9fd5]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 411f4ed69a06f213fb2abb7dbef0be5ce31ff55e Mon Sep 17 00:00:00 2001
+From: Jose Marinho <jose.marinho@arm.com>
+Date: Tue, 29 Oct 2019 09:28:55 +0000
+Subject: [PATCH] driver: firmware: Initial version of ffa driver based on
+ ffa_rel_proto
+
+Initial version of ffa driver based on ffa_rel_proto [1].
+
+[1]: https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=ffa_rel_proto
+
+Squashed in:
+	 firmware: arm64/spci: Add initial SPCI driver
+
+	 Add initial SPCI driver
+
+	 firmware: spci: add conduit selection from DT
+
+	 The driver can use smc or hvc conduits depending on what is
+	 specified in the spci node in the DT.
+
+	 arm64: spci/smccc: Create smc call returning on x0 to x7
+
+	 The new smc call is SMCCCv1.2 compliant.
+
+	 arm_spci: Register Rx/Tx buffers.
+
+	 Registers the Rx/Tx buffers with the SPCI implementation at a higher EL.
+	 The buffers are restricted to 4KB in this implementation.
+
+	 arm_spci: Add SPCI memory sharing mechanisms.
+
+	 Add mem_share and mem_reclaim to the SPCI driver interface.
+	 These two methods allow for the basic memory sharing use-case where
+	 normal world shares a set of pages with secure world.
+	 The memory region description is in this implementation restricted to
+	 4KB (i.e. it must fit in the Tx buffer of the normal world VM).
+
+	 spci_driver/mem_share: Add lock around TX Buffer
+
+	 Ensure we aquire a lock around the TX buffer when sending information to
+	 prevent race conditions.
+
+	 arm_spci: Expose SPCI_PARTITION_INFO_GET
+
+	 Expose the SPCI_PARTITION_INFO_GET ABI to allow querying the system for
+	 information about a set of partitions identified by a specified UUID.
+
+	 The function expects the 128bit UUID to be discovered passed via 4 32bit
+	 words in the format: UUID_0-UUID_1-UUID_2-UUID3 and a pointer to an
+	 array of `spci_partition_info` structs that will allocated and populated
+	 with the discovered partitions information by the SPCI driver.  The
+	 caller is responsible for freeing this memory allocated by the SPCI
+	 driver.
+
+	 The function returns the number of the partitions found (and therefore
+	 the number of elements in the array) or a negative value indicating the
+	 error code if unsuccessful.
+
+	 This implementation currently disallows use of the NULL UUID.
+
+	 arm_spci: Implement rx_release
+
+	 SPCI: Move driver to directory
+
+	 The SPCI driver has a specific directory at drivers/firmware/spci.
+
+	 SPCI: multi-fragment memory share support
+
+	 arm_spci: use scatterlist in mem_share interface
+
+	 Previously an array of page* was passed in the mem_share interface.
+	 This commit introduces a scatterlist as partameter to mem_share function.
+
+	 arm_spci: Add RX_RELEASE return to spci_rx_release
+
+	 A Hypervisor can return SPCI_RX_RELEASE when the PVM calls
+	 SPCI_RX_RELEASE to signal that other VMs need to be scheduled.
+
+	 arm_spci: Change spci_memory_reclaim declaration
+
+	 Function takes an enum mem_clear_t flag to denote if memory should be
+	 cleared upon reclaim.
+
+	 arm_spci: Allow nil UUID in spci_parition_info_get
+
+	 Previously the nil UUID was disallowed.
+
+	 arm_spci: Add support for non-Tx buffer mem_share
+
+	 This commit introduces the buffer*, buffer_size parameters to the
+	 mem_share function. The buffer can be used alternatively to the Tx
+	 buffer. The mem_share function will populate the IPA-contiguous memory
+	 pointed to by buffer using the information in sg.
+
+	 The buffer* must be NULL is mem_share should use the Tx buffer.
+	 The buffer*, if non-NULL, must point to a IPA-contiguous memory region
+	 of size multiple of 4kiB.
+
+	 arm_spci: Support pause/resume in mem_share handle
+
+	 The Hypervisor is allowed to return SPCI_MEM_OPS_PAUSE if a mem_share
+	 operation is taking too long. The PVM must reply with
+	 SPCI_MEM_OPS_RESUME.
+
+	 arm_spci: Ammend debug print.
+
+	 arm_spci: add missing fields in mem descriptor
+
+	 The sender_id, vm_id fields were not properly filled in the mem_share
+	 function.
+
+	 arm_spci: mem_share selection of Tx or alloc buf
+
+	 This commit allows the mem_share invokation to select the  tx buffer or a
+	 dynamically allocated buffer to be used for the transfer of the memory
+	 region description.
+
+	 if use_tx == true: the tx_lock is held until the memory region is fully
+	 transmitted.
+
+	 if use_tx == false: the tx_lock is very briefly held in the preamble
+	 and postamble of the mem_share procedure.
+
+	 arm_spci: Allow compilation for arm arch [smcccv1_2 bits]
+
+	 arm_spci: Allow compilation for arm arch [arm_spci bits]
+
+	 Implement  SPCI features
+
+	 Currently only SPCI_Direct_Req is checked during SPCI driver
+	 initialisation.
+
+	 arm_spci: add err print when features does not report direct_req support
+
+	 arm_spci: refactor mem_share implementation for EAC [arm_spci bits]
+
+	 arm_spci: introduce support for SPCI_INTERRUPT
+
+	 A SP while executing in the context of a SPCI_MSG_SEND_DIRECT_REQ
+	 may be interrupted. In which case the scheduler must be instructed and
+	 be provided with the necessary information to resume the interrupted SP.
+
+	 arm_ffa: optee: Swap spci/SPCI for ffa/FFA. [arm_ffa bits]
+
+	 arm_ffa: Implement ffa_version discovery.
+
+	 arm_ffa: corrections to EAC support.
+
+	 arm_ffa: cast status return to signed for compare
+
+	 arm_ffa: rename 1st member of arm_smcccv1_2_return [arm-smcccv1_2.h bits]
+
+	 The smcccv1_2_return.func is renamed to arg0.
+
+	 arm_ffa: rename 1st member of arm_smcccv1_2_return [arm_ffa bits]
+
+	 The smcccv1_2_return.func is renamed to arg0.
+
+	 arm_ffa: set the default shareability to inner.
+
+	 Pages are shared with inner shareability attribute set in S2.
+
+	 arm_ffa: remove some panic calls
+
+	 Some panics were swaped by pr_warns and an error code return when the
+	 error condition being signaled is predicted by the FFA spec. The panics
+	 issued when an unexpected status is returned from EL2 or
+	 EL3 (behaviour deviating from the FFA spec) are left in the driver.
+
+	 arm_ffa: fix warnings and remove debug print
+
+	 Fixed few warnings related to unused variable and in pr_warn prints
+
+	 arm_ffa: correct checkpatch warnings
+
+	 arm_ffa.h: Split memory access permissions
+
+	 Split the FF-A instruction and data access permissions.
+	 This allows for specifying one attribute but not the other. This is
+	 required for lenders of memory for which must not specify the
+	 instruction access permission.
+
+Signed-off-by: Jose Marinho <jose.marinho@arm.com>
+Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Change-Id: I7bd8cf453e99498ab4df1f01092137a67116d15d
+---
+ arch/arm/kernel/Makefile            |   1 +
+ arch/arm/kernel/smcccv1_2-call.S    |  58 +++
+ arch/arm64/kernel/Makefile          |   2 +-
+ arch/arm64/kernel/smccc_v1_2-call.S |  24 +
+ drivers/firmware/Kconfig            |  11 +
+ drivers/firmware/Makefile           |   1 +
+ drivers/firmware/ffa/Makefile       |   6 +
+ drivers/firmware/ffa/arm_ffa.c      | 782 ++++++++++++++++++++++++++++
+ include/linux/arm-smcccv1_2.h       |  51 ++
+ include/linux/arm_ffa.h             | 235 +++++++++
+ 10 files changed, 1170 insertions(+), 1 deletion(-)
+ create mode 100644 arch/arm/kernel/smcccv1_2-call.S
+ create mode 100644 arch/arm64/kernel/smccc_v1_2-call.S
+ create mode 100644 drivers/firmware/ffa/Makefile
+ create mode 100644 drivers/firmware/ffa/arm_ffa.c
+ create mode 100644 include/linux/arm-smcccv1_2.h
+ create mode 100644 include/linux/arm_ffa.h
+
+diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
+index 8cad59465af3..5be97585d130 100644
+--- a/arch/arm/kernel/Makefile
++++ b/arch/arm/kernel/Makefile
+@@ -101,5 +101,6 @@ obj-$(CONFIG_SMP)		+= psci_smp.o
+ endif
+ 
+ obj-$(CONFIG_HAVE_ARM_SMCCC)	+= smccc-call.o
++obj-$(CONFIG_HAVE_ARM_SMCCC)	+= smcccv1_2-call.o
+ 
+ extra-y := $(head-y) vmlinux.lds
+diff --git a/arch/arm/kernel/smcccv1_2-call.S b/arch/arm/kernel/smcccv1_2-call.S
+new file mode 100644
+index 000000000000..9a577c4045a7
+--- /dev/null
++++ b/arch/arm/kernel/smcccv1_2-call.S
+@@ -0,0 +1,58 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (c) 2020, Linaro Limited
++ */
++#include <linux/linkage.h>
++
++#include <asm-generic/export.h>
++#include <asm/opcodes-sec.h>
++#include <asm/opcodes-virt.h>
++#include <asm/unwind.h>
++
++	/*
++	 * Wrap c macros in asm macros to delay expansion until after the
++	 * SMCCC asm macro is expanded.
++	 */
++	.macro SMCCC_SMC
++	__SMC(0)
++	.endm
++
++	.macro SMCCC_HVC
++	__HVC(0)
++	.endm
++
++	.macro SMCCC instr
++UNWIND(	.fnstart)
++	mov	r12, sp
++	push	{r4-r7}
++UNWIND(	.save	{r4-r7})
++	ldm	r12, {r4-r7}
++	\instr
++	ldr	r12, [sp, #(4 * 8)]
++	stm	r12, {r0-r7}
++	pop	{r4-r7}
++	bx	lr
++UNWIND(	.fnend)
++	.endm
++
++/*
++ * void smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2,
++ *		  unsigned long a3, unsigned long a4, unsigned long a5,
++ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *		  struct arm_smccc_quirk *quirk)
++ */
++ENTRY(__arm_smcccv1_2_smc)
++	SMCCC SMCCC_SMC
++ENDPROC(__arm_smcccv1_2_smc)
++EXPORT_SYMBOL(__arm_smcccv1_2_smc)
++
++/*
++ * void smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
++ *		  unsigned long a3, unsigned long a4, unsigned long a5,
++ *		  unsigned long a6, unsigned long a7, struct arm_smccc_res *res,
++ *		  struct arm_smccc_quirk *quirk)
++ */
++ENTRY(__arm_smcccv1_2_hvc)
++	SMCCC SMCCC_HVC
++ENDPROC(__arm_smcccv1_2_hvc)
++EXPORT_SYMBOL(__arm_smcccv1_2_hvc)
+diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
+index b3995329d9e5..4327ef6f4f8d 100644
+--- a/arch/arm64/kernel/Makefile
++++ b/arch/arm64/kernel/Makefile
+@@ -19,7 +19,7 @@ obj-y			:= debug-monitors.o entry.o irq.o fpsimd.o		\
+ 			   return_address.o cpuinfo.o cpu_errata.o		\
+ 			   cpufeature.o alternative.o cacheinfo.o		\
+ 			   smp.o smp_spin_table.o topology.o smccc-call.o	\
+-			   syscall.o
++			   syscall.o smccc_v1_2-call.o
+ 
+ extra-$(CONFIG_EFI)			:= efi-entry.o
+ 
+diff --git a/arch/arm64/kernel/smccc_v1_2-call.S b/arch/arm64/kernel/smccc_v1_2-call.S
+new file mode 100644
+index 000000000000..518e849409ed
+--- /dev/null
++++ b/arch/arm64/kernel/smccc_v1_2-call.S
+@@ -0,0 +1,24 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2019 Arm Ltd.
++ */
++
++#include <linux/linkage.h>
++
++.macro SMC_CALL conduit
++	\conduit #0
++	ldr x8, [sp]
++	stp x0, x1, [x8]
++	stp x2, x3, [x8, #16]
++	stp x4, x5, [x8, #32]
++	stp x6, x7, [x8, #48]
++	ret
++.endm
++
++ENTRY(__arm_smcccv1_2_hvc)
++	SMC_CALL hvc
++ENDPROC(__arm_smcccv1_2_hvc)
++
++ENTRY(__arm_smcccv1_2_smc)
++	SMC_CALL smc
++ENDPROC(__arm_smcccv1_2_smc)
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index 1bc0e965f2e9..3bcf3d4514e4 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -77,6 +77,17 @@ config ARM_SDE_INTERFACE
+ 	  standard for registering callbacks from the platform firmware
+ 	  into the OS. This is typically used to implement RAS notifications.
+ 
++config ARM_FFA_TRANSPORT
++	bool "ARM Secure Partition Client Interface (FFA)"
++	depends on ARM64 || ARM
++	help
++	  The Secure Partition Client Interface (FFA) is an Arm standard for
++	  communication and memory sharing between entities managed by SMCCC
++	  compliant firmware.
++
++	  This driver provides interface for all the client drivers making
++	  use of the features offered by FFA.
++
+ config EDD
+ 	tristate "BIOS Enhanced Disk Drive calls determine boot disk"
+ 	depends on X86
+diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
+index 64f5391e5749..10041c5f4d07 100644
+--- a/drivers/firmware/Makefile
++++ b/drivers/firmware/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_TURRIS_MOX_RWTM)	+= turris-mox-rwtm.o
+ 
+ obj-$(CONFIG_ARM_SCMI_PROTOCOL)	+= arm_scmi/
+ obj-y				+= psci/
++obj-y				+= ffa/
+ obj-y				+= broadcom/
+ obj-y				+= meson/
+ obj-$(CONFIG_GOOGLE_FIRMWARE)	+= google/
+diff --git a/drivers/firmware/ffa/Makefile b/drivers/firmware/ffa/Makefile
+new file mode 100644
+index 000000000000..37f4ccae197b
+--- /dev/null
++++ b/drivers/firmware/ffa/Makefile
+@@ -0,0 +1,6 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# Makefile for the linux kernel.
++#
++obj-$(CONFIG_ARM_FFA_TRANSPORT)	+= arm_ffa.o
++ccflags-y += -Og
+diff --git a/drivers/firmware/ffa/arm_ffa.c b/drivers/firmware/ffa/arm_ffa.c
+new file mode 100644
+index 000000000000..21838f8c4632
+--- /dev/null
++++ b/drivers/firmware/ffa/arm_ffa.c
+@@ -0,0 +1,782 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Secure Partitions Communication Interface (FFA) Protocol driver
++ *
++ * FFA is a system message passing and memory sharing protocol allowing for
++ * execution contexts to exchange information with other execution contexts
++ * residing on other Secure Partitions or Virtual Machines managed by any FFA
++ * compliant firmware framework.
++ *
++ * Copyright (C) 2019, 2020 Arm Ltd.
++ */
++#define DEBUG
++
++#include <linux/platform_device.h>
++#include <linux/arm_ffa.h>
++#include <linux/arm-smcccv1_2.h>
++#include <linux/of_address.h>
++#include <linux/of_platform.h>
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/mutex.h>
++#include <linux/slab.h>
++#include <linux/scatterlist.h>
++
++
++static DEFINE_MUTEX(rx_lock);
++static DEFINE_MUTEX(tx_lock);
++
++static ffa_sp_id_t vm_id;
++
++static struct page *rx_buffer;
++static struct page *tx_buffer;
++
++static struct arm_smcccv1_2_return
++(*arm_ffa_smccc)(u32 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,
++		  u64 arg5, u64 arg6, u64 arg7);
++
++#define FFA_DEFINE_CALL(conduit)					\
++static struct arm_smcccv1_2_return					\
++arm_ffa_##conduit(u32 func, u64 arg1, u64 arg2, u64 arg3, u64 arg4,	\
++		   u64 arg5, u64 arg6, u64 arg7)			\
++{									\
++	struct arm_smcccv1_2_return smccc_ret;				\
++									\
++	__arm_smcccv1_2_##conduit(func, arg1, arg2, arg3, arg4, arg5,	\
++				  arg6,	arg7, &smccc_ret);		\
++									\
++	return smccc_ret;						\
++}
++
++FFA_DEFINE_CALL(smc)
++FFA_DEFINE_CALL(hvc)
++
++static u32 sender_receiver_pack(u32 src_id, u32 dst_id)
++{
++	return (((src_id << 16) & 0xffff0000) | (dst_id & 0xffff));
++}
++
++int ffa_msg_send(ffa_sp_id_t dst_id, u32 len, u32 attributes)
++{
++	struct arm_smcccv1_2_return msg_send_return;
++
++	/* w1[32:16] Sender endpoint ID, w1[15:0] destination endpoint id. */
++	u32 sender_receiver = sender_receiver_pack(vm_id, dst_id);
++
++	msg_send_return = arm_ffa_smccc(FFA_MSG_SEND_32, sender_receiver,
++					 0, len, attributes, 0, 0, 0);
++
++	if (msg_send_return.arg0  == FFA_ERROR_32) {
++		switch ((int)msg_send_return.arg2) {
++		case FFA_INVALID_PARAMETERS:
++			return -ENXIO;
++		case FFA_DENIED:
++		case FFA_BUSY:
++			return -EAGAIN;
++		default:
++			panic("%s: Unhandled return code (%lld)\n", __func__,
++			      msg_send_return.arg2);
++		}
++	}
++	return 0;
++}
++
++struct arm_smcccv1_2_return
++ffa_msg_send_direct_req(ffa_sp_id_t dst_id, u64 w3, u64 w4, u64 w5,
++			 u64 w6, u64 w7)
++{
++	struct arm_smcccv1_2_return ret;
++
++	/* w1[32:16] Sender endpoint ID, w1[15:0] destination endpoint id. */
++	u32 sender_receiver = sender_receiver_pack(vm_id, dst_id);
++
++	ret = arm_ffa_smccc(FFA_MSG_SEND_DIRECT_REQ_32, sender_receiver, 0,
++			     w3, w4, w5, w6, w7);
++
++	while (ret.arg0 != FFA_MSG_SEND_DIRECT_RESP_32 &&
++		ret.arg0 != FFA_SUCCESS_32) {
++		if (ret.arg0 == FFA_ERROR_32) {
++			pr_err("%s: Error sending message %llu\n", __func__,
++				ret.arg0);
++			switch ((int)ret.arg1) {
++			case FFA_INVALID_PARAMETERS:
++				ret.arg0 = -ENXIO;
++				goto out;
++
++			case FFA_DENIED:
++			case FFA_NOT_SUPPORTED:
++				ret.arg0 = -EIO;
++				goto out;
++
++			case FFA_BUSY:
++				ret.arg0 = -EAGAIN;
++				goto out;
++			}
++		} else if (ret.arg0 == FFA_INTERRUPT_32) {
++			ret = arm_ffa_smccc(FFA_RUN_32, ret.arg1,
++				0, 0, 0, 0, 0, 0);
++		}
++
++	}
++
++	ret.arg0 = 0;
++
++out:
++	return ret;
++}
++
++static int ffa_share_next_frag(u64 handle, u32 frag_len, u32 *tx_offset)
++{
++
++	struct arm_smcccv1_2_return smccc_return;
++	u32 handle_high = (handle >> 32) & 0xffffffff;
++	u32 handle_low = handle & 0xffffffff;
++
++	smccc_return =
++		arm_ffa_smccc(FFA_MEM_FRAG_TX_32, handle_low,
++			handle_high, frag_len, 0, 0, 0, 0);
++
++	while (smccc_return.arg0 != FFA_MEM_FRAG_RX_32) {
++
++		if (smccc_return.arg0 == FFA_ERROR_32) {
++			switch ((int)smccc_return.arg2) {
++			case FFA_INVALID_PARAMETERS:
++				return -ENXIO;
++			case FFA_NOT_SUPPORTED:
++				return -ENODEV;
++			default:
++				pr_warn("%s: Unknown Error code %llx\n",
++					__func__, smccc_return.arg2);
++				return -EIO;
++			}
++		}
++
++		if (smccc_return.arg0 == FFA_MEM_OP_PAUSE_32) {
++
++			smccc_return = arm_ffa_smccc(FFA_MEM_OP_RESUME_32,
++				smccc_return.arg1, smccc_return.arg2, 0, 0, 0,
++				0, 0);
++		}
++	}
++
++	*tx_offset = smccc_return.arg3;
++
++	return 0;
++}
++
++static int ffa_share_init_frag(phys_addr_t buffer, u32 buffer_size,
++	u32 fragment_len, u32 total_len, u64 *handle)
++{
++
++	struct arm_smcccv1_2_return smccc_return;
++
++	smccc_return =
++		arm_ffa_smccc(FFA_MEM_SHARE_64, total_len, fragment_len, buffer,
++		buffer_size, 0, 0, 0);
++
++	while (smccc_return.arg0 != FFA_SUCCESS_32) {
++
++		if (smccc_return.arg0 == FFA_ERROR_32) {
++			switch ((int)smccc_return.arg2) {
++			case FFA_INVALID_PARAMETERS:
++				return -ENXIO;
++			case FFA_DENIED:
++				return -EIO;
++			case FFA_NO_MEMORY:
++				return -ENOMEM;
++			case FFA_ABORTED:
++				return -EAGAIN;
++			default:
++				pr_warn("%s: Unknown Error code %llx\n",
++					__func__, smccc_return.arg2);
++				return -EIO;
++			}
++		}
++
++		if (smccc_return.arg0 == FFA_MEM_OP_PAUSE_32) {
++
++			smccc_return = arm_ffa_smccc(FFA_MEM_OP_RESUME_32,
++				smccc_return.arg1, smccc_return.arg2, 0, 0, 0,
++				0, 0);
++		}
++	}
++
++	*handle = (smccc_return.arg3 << 32) | smccc_return.arg2;
++
++	return 0;
++}
++
++static inline u32 compute_composite_offset(u32 num_attributes)
++{
++	u32 composite_offset = offsetof(struct ffa_mem_region,
++		endpoints[num_attributes]);
++
++	/* ensure composite are 8 byte aligned. */
++	if (composite_offset & 0x7)
++		return (composite_offset & (~(u32)0x7)) + 0x8;
++
++	return composite_offset;
++}
++
++static inline u32 compute_constituent_offset(u32 num_attributes)
++{
++	u32 constituent_offset = offsetof(struct ffa_mem_region,
++		endpoints[num_attributes]) +
++		offsetof(struct ffa_composite_memory_region, constituents[0]);
++
++	/* ensure constituents are 8 byte aligned. */
++	if (constituent_offset & 0x7)
++		return (constituent_offset & (~(u32)0x7)) + 0x8;
++
++	return constituent_offset;
++}
++
++static inline u32 compute_region_length(u32 num_constituents,
++	u32 num_attributes)
++{
++	/* This assumes that there is a single ffa_composite_memory_region. */
++	return compute_constituent_offset(num_attributes) +
++		sizeof(struct ffa_mem_region_constituent)*num_constituents;
++}
++
++static int ffa_rx_release(void)
++{
++	struct arm_smcccv1_2_return rx_release_return;
++
++	rx_release_return = arm_ffa_smccc(FFA_RX_RELEASE_32,
++					      0, 0, 0, 0, 0, 0, 0);
++
++	if (rx_release_return.arg0 == FFA_ERROR_32) {
++		switch ((int)rx_release_return.arg2) {
++		case FFA_DENIED:
++			return -EAGAIN;
++		default:
++			panic("%s: Unhandled return code (%lld)\n", __func__,
++			      rx_release_return.arg2);
++		}
++	}
++
++	if (rx_release_return.arg0 == FFA_RX_RELEASE_32) {
++		/*
++		 * FFA implementation returned FFA_RX_RELEASE which signals
++		 * the PVM that other VMs need to be scheduled.
++		 */
++		return 1;
++	}
++
++	return 0;
++}
++
++static uint32_t ffa_get_num_pages_sg(struct scatterlist *sg)
++{
++	uint32_t num_pages = 0;
++
++	do {
++		num_pages += sg->length/PAGE_SIZE;
++	} while ((sg = sg_next(sg)));
++
++	return num_pages;
++}
++
++static inline struct ffa_memory_region_attribute ffa_set_region_normal(
++	enum ffa_mem_cacheability cacheability,
++	enum ffa_mem_shareability shareability)
++{
++	struct ffa_memory_region_attribute attr = {0};
++
++	attr.attribute = (FFA_MEM_NORMAL << FFA_MEMTYPE_OFFSET) |
++		(cacheability << FFA_CACHEABILITY_OFFSET) | shareability;
++
++	return attr;
++}
++
++static inline struct ffa_memory_region_attribute ffa_set_region_device(
++	enum ffa_mem_device_type device_type)
++{
++	struct ffa_memory_region_attribute attr = {0};
++
++	attr.attribute = (FFA_MEM_DEVICE << FFA_MEMTYPE_OFFSET) |
++		(device_type << FFA_DEVICE_OFFSET);
++
++	return attr;
++}
++
++static inline int ffa_transmit_fragment(u32 *tx_offset, phys_addr_t buffer,
++	u32 buffer_size, u32 frag_len, u32 total_len, u64 *handle)
++{
++	int rc;
++
++	if (*tx_offset == 0) {
++		rc = ffa_share_init_frag(buffer, buffer_size,
++			frag_len, total_len, handle);
++
++		*tx_offset = frag_len;
++	} else
++		rc = ffa_share_next_frag(*handle, frag_len, tx_offset);
++
++
++	return rc;
++}
++
++/*
++ * Share a set of pages with a list of destination endpoints.
++ * Returns a system-wide unique handle
++ */
++static int _ffa_share_memory(u32 tag, enum mem_clear_t flags,
++	struct ffa_mem_region_attributes *attrs,
++	u32 num_attrs, struct scatterlist *sg, u32 nents,
++	ffa_mem_handle_t *handle, phys_addr_t buffer, uint32_t buffer_size)
++{
++	struct ffa_mem_region *mem_region;
++	u32 index;
++	u32 num_constituents;
++	struct ffa_mem_region_constituent *constituents;
++	u32 total_len;
++	u32 fragment_len = sizeof(struct ffa_mem_region);
++	u32 max_fragment_size;
++	int rc = 0;
++	u32 tx_offset = 0;
++	struct ffa_composite_memory_region *composite = NULL;
++
++	if (buffer) {
++
++		BUG_ON(!buffer_size);
++		max_fragment_size = buffer_size * FFA_BASE_GRANULE_SIZE;
++		mem_region = phys_to_virt(buffer);
++
++	} else {
++
++		BUG_ON(buffer_size);
++		mem_region = (struct ffa_mem_region *)page_address(tx_buffer);
++		max_fragment_size = FFA_BASE_GRANULE_SIZE;
++
++	}
++
++	mem_region->flags = flags;
++	mem_region->tag = tag;
++	mem_region->sender_id = vm_id;
++	mem_region->region_attr = ffa_set_region_normal(FFA_WRITE_BACK,
++		FFA_INNER_SHAREABLE);
++	composite = ffa_get_composite(mem_region, num_attrs);
++	composite->total_page_count = ffa_get_num_pages_sg(sg);
++
++	fragment_len = compute_constituent_offset(num_attrs);
++
++	/* Ensure attribute description fits within the Tx buffer. */
++	if (fragment_len > max_fragment_size)
++		return -ENXIO;
++
++	constituents = (struct ffa_mem_region_constituent *)
++		(((void *)mem_region) + fragment_len);
++
++	composite->constituent_count = nents;
++	total_len = compute_region_length(nents, num_attrs);
++
++	for (index = 0; index < num_attrs; index++) {
++		mem_region->endpoints[index].receiver = attrs[index].receiver;
++		mem_region->endpoints[index].attrs =
++			attrs[index].attrs;
++
++		mem_region->endpoints[index].composite_off =
++			compute_composite_offset(num_attrs);
++	}
++	mem_region->endpoint_count = num_attrs;
++
++	num_constituents = 0;
++
++	do {
++		phys_addr_t address;
++
++		/*
++		 * If current fragment size equal Tx size trigger fragment
++		 * transfer.
++		 */
++		if (fragment_len == max_fragment_size) {
++
++			/* Transmit fragment. */
++			rc = ffa_transmit_fragment(&tx_offset, buffer,
++				buffer_size, fragment_len, total_len, handle);
++
++			if (rc < 0)
++				return -ENXIO;
++
++
++			constituents =
++				(struct ffa_mem_region_constituent *)mem_region;
++
++			num_constituents = 0;
++			fragment_len = 0;
++		}
++
++		address = sg_phys(sg);
++
++		/*
++		 * Detect if any part of the constituent region surpasses the Tx
++		 * region.
++		 */
++		if (((void *) &constituents[num_constituents])
++			- (void *)mem_region > max_fragment_size) {
++			pr_err("%s: memory region fragment greater that the Tx buffer",
++				__func__);
++			return -EFAULT;
++		}
++#if 0
++		pr_devel("arm_ffa mem_share pa=%#lX\n", address);
++#endif
++		constituents[num_constituents].address = address;
++		constituents[num_constituents].page_count =
++			sg->length/PAGE_SIZE;
++		num_constituents++;
++		fragment_len += sizeof(struct ffa_mem_region_constituent);
++
++
++	} while ((sg = sg_next(sg)));
++
++	rc = ffa_transmit_fragment(&tx_offset, buffer, buffer_size,
++		fragment_len, total_len, handle);
++
++	return rc;
++}
++
++/*
++ * Share a set of pages with a list of destination endpoints.
++ *
++ * Returns a system-wide unique handle
++ */
++static int ffa_share_memory(u32 tag, enum mem_clear_t flags,
++	struct ffa_mem_region_attributes *attrs,
++	u32 num_attrs, struct scatterlist *sg, u32 nents,
++	ffa_mem_handle_t *global_handle, bool use_tx)
++{
++	u32 buffer_size = 0;
++	phys_addr_t buffer_pa = 0;
++	int ret;
++	struct page *buffer_page = NULL;
++
++	if (!use_tx) {
++		/* Allocate buffer for this mem_share operation. */
++		buffer_page = alloc_page(GFP_KERNEL);
++		if (IS_ERR_OR_NULL(buffer_page)) {
++			/* print error. Return as tx lock is not held. */
++			pr_err("%s: unable to allocate buffer", __func__);
++			return -ENOMEM;
++		}
++
++		buffer_pa = page_to_phys(buffer_page);
++
++		buffer_size = 1;
++	}
++
++	if (use_tx)
++		mutex_lock(&tx_lock);
++
++	ret = _ffa_share_memory(tag, flags, attrs, num_attrs, sg, nents,
++		global_handle, buffer_pa, buffer_size);
++
++	if (use_tx)
++		mutex_unlock(&tx_lock);
++
++	return ret;
++}
++
++static int ffa_memory_reclaim(ffa_mem_handle_t global_handle,
++	enum mem_clear_t flags)
++{
++
++	struct arm_smcccv1_2_return smccc_return;
++	u32 handle_high = (global_handle >> 32) & 0xffffffff;
++	u32 handle_low = global_handle & 0xffffffff;
++
++	smccc_return = arm_ffa_smccc(FFA_MEM_RECLAIM_32, handle_low,
++		handle_high, flags, 0, 0, 0, 0);
++
++	if (smccc_return.arg0 == FFA_ERROR_32) {
++		pr_err("%s: Error sending message %llu\n", __func__,
++			smccc_return.arg0);
++		switch ((int)smccc_return.arg2) {
++		case FFA_INVALID_PARAMETERS:
++			return -ENXIO;
++		case FFA_DENIED:
++		case FFA_NOT_SUPPORTED:
++			return -EIO;
++		case FFA_BUSY:
++			return -EAGAIN;
++		default:
++			pr_warn("%s: Unknown Error code %llx\n", __func__,
++				smccc_return.arg2);
++			return -EIO;
++		}
++	}
++
++	return 0;
++}
++
++/*
++ * Returns a negative value if function not supported. Otherwise returns w2,
++ * supplying optional feature parameter else 0.
++ */
++
++static int ffa_features(uint32_t function_id)
++{
++	struct arm_smcccv1_2_return features_return =
++		arm_ffa_smccc(FFA_FEATURES_32, function_id, 0, 0, 0, 0, 0, 0);
++
++	if (features_return.arg0 == FFA_ERROR_32) {
++		switch ((int)features_return.arg2) {
++		case FFA_NOT_SUPPORTED:
++			return -ENODEV;
++		default:
++			panic("%s: Unhandled return code (%lld)\n", __func__,
++			      features_return.arg2);
++		}
++	} else {
++		return features_return.arg2;
++	}
++}
++
++static ffa_sp_id_t ffa_id_get(ffa_sp_id_t *vm_id_p)
++{
++	struct  arm_smcccv1_2_return id_get_return =
++		arm_ffa_smccc(FFA_ID_GET_32, 0, 0, 0, 0, 0, 0, 0);
++
++	if (id_get_return.arg0 == FFA_ERROR_32) {
++		pr_warn("%s: failed to obtain vm id\n", __func__);
++		return -EIO;
++	}
++
++	*vm_id_p = id_get_return.arg2 & 0xffff;
++
++	return 0;
++}
++
++static int ffa_partition_info_get(uint32_t uuid0, uint32_t uuid1,
++				     uint32_t uuid2, uint32_t uuid3,
++				     struct ffa_partition_info **buffer)
++{
++	int rc = 0;
++	uint32_t count;
++	struct ffa_partition_info *info =
++		(struct ffa_partition_info *) page_address(rx_buffer);
++	struct arm_smcccv1_2_return partition_info_get_return;
++
++	mutex_lock(&rx_lock);
++	partition_info_get_return = arm_ffa_smccc(FFA_PARTITION_INFO_GET_32,
++						   uuid0, uuid1, uuid2, uuid3,
++						   0, 0, 0);
++
++	if (partition_info_get_return.arg0 == FFA_ERROR_32) {
++		switch ((int)partition_info_get_return.arg2) {
++		case FFA_INVALID_PARAMETERS:
++			rc = -ENXIO;
++			goto err;
++		case FFA_NO_MEMORY:
++			rc = -ENOMEM;
++			goto err;
++		case FFA_NOT_SUPPORTED:
++			rc = -ENODEV;
++			goto err;
++		default:
++			panic("%s: Unhandled return code (%lld)\n", __func__,
++			      partition_info_get_return.arg2);
++		}
++	}
++
++	count = partition_info_get_return.arg2;
++
++	/* Allocate and copy the info structs.
++	 * Client is responsible for freeing.
++	 */
++	*buffer = kzalloc(sizeof(struct ffa_partition_info) * count,
++			  GFP_KERNEL);
++	if (*buffer == NULL) {
++		rc = -ENOMEM;
++		goto err;
++	}
++	memcpy(*buffer, info, sizeof(struct ffa_partition_info) * count);
++
++	ffa_rx_release();
++
++	rc = count;
++err:
++	mutex_unlock(&rx_lock);
++
++	return rc;
++}
++
++static struct ffa_ops ffa_ops = {
++	.async_msg_send = ffa_msg_send,
++	.sync_msg_send = ffa_msg_send_direct_req,
++	.mem_share = ffa_share_memory,
++	.mem_reclaim = ffa_memory_reclaim,
++	.partition_info_get = ffa_partition_info_get,
++};
++
++struct ffa_ops *get_ffa_ops(void)
++{
++	return &ffa_ops;
++}
++EXPORT_SYMBOL_GPL(get_ffa_ops);
++
++static int ffa_dt_init(struct device_node *np)
++{
++	const char *conduit;
++
++	pr_info("FFA: obtaining conduit from DT.\n");
++
++	if (of_property_read_string(np, "conduit", &conduit)) {
++		pr_warn("FFA: cannot find conduit in DT\n");
++		return -ENXIO;
++	}
++
++	if (!strcmp("smc", conduit))
++		arm_ffa_smccc = arm_ffa_smc;
++	else if (!strcmp("hvc", conduit))
++		arm_ffa_smccc = arm_ffa_hvc;
++	else {
++		pr_warn("%s: unrecognized FFA conduit\n", __func__);
++		return -EIO;
++	}
++
++	return 0;
++}
++
++static const struct of_device_id ffa_of_match[] = {
++	{.compatible = "arm,ffa"},
++	{},
++};
++
++static int ffa_rxtx_map(uintptr_t tx_page, uintptr_t rx_page)
++{
++	struct arm_smcccv1_2_return map_return;
++
++	map_return = arm_ffa_smccc(FFA_RXTX_MAP_32, tx_page,
++					 rx_page, 1, 0, 0, 0, 0);
++
++	if (map_return.arg0 == FFA_ERROR_32) {
++		switch ((int)map_return.arg2) {
++		case FFA_INVALID_PARAMETERS:
++			return -ENXIO;
++		case FFA_DENIED:
++			return -EAGAIN;
++		case FFA_NO_MEMORY:
++			return -ENOMEM;
++		case FFA_NOT_SUPPORTED:
++			return -ENODEV;
++
++		default:
++			panic("%s: Unhandled return code (%lld)\n", __func__,
++			      map_return.arg2);
++		}
++	}
++
++	return 0;
++}
++
++static int ffa_version_check(void)
++{
++	struct arm_smcccv1_2_return version_return;
++	u16 major = 1;
++	u16 minor = 0;
++	u32 hv_version;
++
++	version_return = arm_ffa_smccc(FFA_VERSION_32, ((u32)major<<16)|minor,
++		 0, 0, 0, 0, 0, 0);
++
++	if ((int)version_return.arg0 == FFA_NOT_SUPPORTED) {
++		pr_err("%s: FFA ABI is not supported at higher exception levels\n",
++			__func__);
++		return -ENODEV;
++	}
++
++	hv_version = version_return.arg0;
++
++	if ((hv_version>>16) == major)
++		if ((hv_version & 0xffff) >= minor)
++			return 0;
++
++	pr_err("%s: incompatible FFA ABI at higher exception level (%x)\n",
++		__func__, hv_version);
++	return -ENODEV;
++}
++
++static int ffa_probe(struct platform_device *pdev)
++{
++	int ret;
++
++	ret = ffa_dt_init(pdev->dev.of_node);
++	if (ret) {
++		pr_warn("%s: FFA driver initialization failed\n", __func__);
++		return ret;
++	}
++
++	ret = ffa_version_check();
++	if (ret)
++		return ret;
++
++	/* Initialize VM ID. */
++	ret = ffa_id_get(&vm_id);
++	if (ret) {
++		pr_warn("%s: failed to obtain own FFA endpoint ID\n", __func__);
++		return ret;
++	}
++
++	if (ffa_features(FFA_MSG_SEND_DIRECT_REQ_32)) {
++		pr_err("%s: FFA implementation at EL2 does not support FFA_MSG_SEND_DIRECT_REQ_32\n",
++			__func__);
++		return -ENXIO;
++	}
++
++	/* Allocate Rx buffer. */
++	rx_buffer = alloc_page(GFP_KERNEL);
++
++	/*
++	 * Ensure buffer was correctly allocated and that the refcout was
++	 * incremented.
++	 */
++	if (!rx_buffer || !try_get_page(rx_buffer)) {
++		pr_err("%s: failed to allocate FFA Rx buffer\n", __func__);
++		return -ENOMEM;
++	}
++
++	/* Allocate Tx buffer. */
++	tx_buffer = alloc_page(GFP_KERNEL);
++
++	/*
++	 * Ensure buffer was correctly allocated and that the refcout was
++	 * incremented.
++	 */
++	if (!tx_buffer || !try_get_page(rx_buffer)) {
++		put_page(rx_buffer);
++		__free_page(rx_buffer);
++
++		pr_err("%s: failed to allocate FFA Tx buffer\n", __func__);
++		return -ENOMEM;
++	}
++
++	/* Register the RxTx buffers with the FFA supervisor implementation. */
++	ret = ffa_rxtx_map(page_to_phys(tx_buffer), page_to_phys(rx_buffer));
++	if (ret) {
++		put_page(rx_buffer);
++		put_page(tx_buffer);
++		__free_page(rx_buffer);
++		__free_page(tx_buffer);
++
++		pr_err("%s: failed to register FFA RxTx buffers\n", __func__);
++		return ret;
++	}
++
++	return 0;
++}
++
++static struct platform_driver ffa_driver = {
++	.driver = {
++		.name = "ffa_protocol",
++		.of_match_table = ffa_of_match,
++	},
++	.probe = ffa_probe,
++};
++module_platform_driver(ffa_driver);
++
++MODULE_AUTHOR("Arm");
++MODULE_DESCRIPTION("Arm FFA transport driver");
++MODULE_LICENSE("GPL v2");
+diff --git a/include/linux/arm-smcccv1_2.h b/include/linux/arm-smcccv1_2.h
+new file mode 100644
+index 000000000000..a622cc352ae1
+--- /dev/null
++++ b/include/linux/arm-smcccv1_2.h
+@@ -0,0 +1,51 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++/*
++ * Copyright (C) 2019 Arm Ltd.
++ */
++
++//#if defined(ARM64)
++#if CONFIG_ARM64 
++struct arm_smcccv1_2_return {
++	u64 arg0;
++	u64 arg1;
++	u64 arg2;
++	u64 arg3;
++	u64 arg4;
++	u64 arg5;
++	u64 arg6;
++	u64 arg7;
++};
++#elif CONFIG_ARM
++struct arm_smcccv1_2_return {
++	u32 arg0;
++	u32 arg1;
++	u32 arg2;
++	u32 arg3;
++	u32 arg4;
++	u32 arg5;
++	u32 arg6;
++	u32 arg7;
++};
++#endif
++
++/**
++ * __arm_smcccv1_2_hvc() - make HVC calls
++ * @a0-a7: arguments passed in registers 0 to 7
++ * @res: result values from registers 0 to 7
++ */
++asmlinkage
++void __arm_smcccv1_2_hvc(unsigned long a0, unsigned long a1, unsigned long a2,
++			 unsigned long a3, unsigned long a4, unsigned long a5,
++			 unsigned long a6, unsigned long a7,
++			 struct arm_smcccv1_2_return  *res);
++
++/**
++ * __arm_smcccv1_2_smc() - make SMC calls
++ * @a0-a7: arguments passed in registers 0 to 7
++ * @res: result values from registers 0 to 7
++ */
++asmlinkage
++void __arm_smcccv1_2_smc(unsigned long a0, unsigned long a1, unsigned long a2,
++			 unsigned long a3, unsigned long a4, unsigned long a5,
++			 unsigned long a6, unsigned long a7,
++			 struct arm_smcccv1_2_return  *res);
+diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
+new file mode 100644
+index 000000000000..d3c80b7f9e07
+--- /dev/null
++++ b/include/linux/arm_ffa.h
+@@ -0,0 +1,235 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright (C) 2019, 2020 Arm Ltd.
++ */
++
++#ifndef __LINUX_ARM_FFA_H
++#define __LINUX_ARM_FFA_H
++
++#define FFA_ERROR_32                 0x84000060
++#define FFA_SUCCESS_32               0x84000061
++#define FFA_INTERRUPT_32             0x84000062
++#define FFA_VERSION_32               0x84000063
++#define FFA_FEATURES_32              0x84000064
++#define FFA_RX_RELEASE_32            0x84000065
++#define FFA_RXTX_MAP_32              0x84000066
++
++#define FFA_PARTITION_INFO_GET_32    0x84000068
++#define FFA_ID_GET_32                0x84000069
++
++#define FFA_RUN_32                   0x8400006D
++#define FFA_MSG_SEND_32              0x8400006E
++#define FFA_MSG_SEND_DIRECT_REQ_32   0x8400006F
++#define FFA_MSG_SEND_DIRECT_RESP_32  0x84000070
++#define FFA_MEM_RECLAIM_32           0x84000077
++#define FFA_MEM_OP_PAUSE_32          0x84000078
++#define FFA_MEM_OP_RESUME_32         0x84000079
++
++#define FFA_MEM_SHARE_64             0xC4000073
++
++#define FFA_MEM_FRAG_RX_32			  0x8400007A
++#define FFA_MEM_FRAG_TX_32			  0x8400007B
++
++/* FFA error codes. */
++#define FFA_SUCCESS            (0)
++#define FFA_NOT_SUPPORTED      (-1)
++#define FFA_INVALID_PARAMETERS (-2)
++#define FFA_NO_MEMORY          (-3)
++#define FFA_BUSY               (-4)
++#define FFA_INTERRUPTED        (-5)
++#define FFA_DENIED             (-6)
++#define FFA_RETRY              (-7)
++#define FFA_ABORTED            (-8)
++
++#define FFA_BASE_GRANULE_SIZE 4096
++
++struct scatterlist;
++
++enum ffa_mem_permission {
++	FFA_MEM_R   = 0x1,
++	FFA_MEM_RW  = 0x2,
++	FFA_MEM_XN  = 0x4,
++	FFA_MEM_X   = 0x8,
++};
++
++#define FFA_MEMTYPE_OFFSET 4
++enum ffa_mem_type {
++	FFA_MEM_DEVICE = 0x1,
++	FFA_MEM_NORMAL = 0x2,
++};
++
++
++#define FFA_CACHEABILITY_OFFSET 2
++enum ffa_mem_cacheability {
++	FFA_NON_CACHEABLE = 0x1,
++	FFA_WRITE_BACK = 0x3,
++};
++
++enum ffa_mem_shareability {
++	FFA_NON_SHAREABLE,
++	FFA_OUTER_SHAREABLE = 0x2,
++	FFA_INNER_SHAREABLE = 0x3,
++};
++
++#define FFA_DEVICE_OFFSET 2
++enum ffa_mem_device_type {
++	FFA_NGNRNE,
++	FFA_NGNRE,
++	FFA_NGRE,
++	FFA_GRE,
++};
++
++enum mem_clear_t {
++	FFA_KEEP_MEMORY,
++	FFA_CLEAR_MEMORY,
++};
++
++typedef u64 ffa_mem_handle_t;
++
++/* The type of an FFA endpoint ID */
++typedef u16 ffa_sp_id_t;
++
++struct ffa_mem_region_constituent {
++	u64 address;
++	u32 page_count;
++	u32 reserved_12_15;
++};
++
++struct ffa_composite_memory_region {
++
++	uint32_t total_page_count;
++	uint32_t constituent_count;
++
++	uint64_t reserved_0;
++
++	struct ffa_mem_region_constituent constituents[];
++};
++
++struct ffa_mem_region_attributes {
++	ffa_sp_id_t receiver;
++	u8 attrs;
++	u32 composite_off;
++	u64 reserved_8_15;
++};
++
++/* Table 43 */
++struct ffa_memory_region_attribute {
++	uint8_t attribute;
++};
++
++struct ffa_mem_region {
++	u16 sender_id;
++	struct ffa_memory_region_attribute region_attr;
++	u8 reserved_0;
++	u32 flags;
++	u64 handle;
++	u64 tag;
++	u32 reserved_1;
++	u32 endpoint_count;
++	struct ffa_mem_region_attributes endpoints[];
++};
++
++static inline struct ffa_composite_memory_region *
++ffa_get_composite(struct ffa_mem_region *mem_region, u32 num_endpoints)
++{
++	struct ffa_composite_memory_region *composite;
++
++	composite = (struct ffa_composite_memory_region *)
++		(&mem_region->endpoints[num_endpoints]);
++	return composite;
++}
++
++
++struct ffa_partition_info {
++		/** The ID of the VM the information is about. */
++		ffa_sp_id_t id;
++		/**
++		 * The number of execution contexts implemented by the
++		 * partition.
++		 */
++		uint16_t execution_context;
++		/**
++		 * The Partition's properties, e.g. supported messaging
++		 * methods
++		 */
++		uint32_t partition_properties;
++};
++
++
++/**
++ * struct ffa_ops - represents the various FFA protocol operations
++ * available for an SCPI endpoint.
++ */
++struct ffa_ops {
++	int (*async_msg_send)(ffa_sp_id_t dst_id, u32 len, u32 attributes);
++	struct arm_smcccv1_2_return
++	(*sync_msg_send)(ffa_sp_id_t dst_id, u64 w3, u64 w4, u64 w5,
++			 u64 w6, u64 w7);
++
++	/**
++	 * Registers a memory region with the FFA implementation.
++	 *
++	 * Params:
++	 *  - tag: Implementation defined value.
++	 *  - flags:
++	 *   - FFA_KEEP_MEMORY: DO not clear the memory region;
++	 *   - FFA_CLEAR_MEMORY: Clear the memory region.
++	 *  - attrs[]: Array of destination VMs and permissions with which the
++	 *     Stage-2 mappings are set.
++	 *  - num_attrs: Count of elements pointed to by attrs.
++	 *  - sg: scatter list holding the pages to be shared.
++	 *  - global_handle: A system-wide unique handle referring to the shared
++	 *     set of physical pages being shared.
++	 *  - use_tx: select if memorry region description is transmitted in tx
++	 *     or in a dynamically allocated buffer. When using the tx buffer a
++	 *     global lock on the tx buffer will be held.
++	 *
++	 * Return: 0 in case of success, otherwise a negative value
++	 * (error code).
++	 */
++	int (*mem_share)(u32 tag, enum mem_clear_t flags,
++			  struct ffa_mem_region_attributes attrs[],
++			  u32 num_attrs, struct scatterlist *sg, u32 nents,
++			  ffa_mem_handle_t *global_handle, bool use_tx);
++
++	/**
++	 * Reclaims a memory region previously registered with the FFA
++	 *  implementation.
++	 * Params:
++	 *  - global_handle: The global identifier of the memory region being
++	 *     reclaimed.
++	 *  - clear_memory: Set if the memory is meant to be cleared before
++	 *     being mapped in the owner's Stage-2.
++	 *
++	 * Return: 0 in case of success, otherwise a negative value
++	 * (error code).
++	 */
++	int (*mem_reclaim)(ffa_mem_handle_t global_handle,
++		enum mem_clear_t flags);
++	/**
++	 * Returns information on a sub-set of partitions within a system
++	 * identified by a UUID.
++	 * Params:
++	 *  - uuid0-3: The 128 bit UUID of the desired partition(s) represented
++	 *              as 4 32 bit uints in form: uuid0-uuid1-uuid2-uuid3.
++	 *  - ffa_partition_info**: A pointer to an array of
++	 *	                     `ffa_parition_info` structs that will be
++	 *	                     allocated and populated with the
++	 *	                     discovered partitions information. The
++	 *	                     caller is responsible for freeing the
++	 *	                     memory allocated by the FFA driver.
++	 * Return: The number of discovered partitions in the system and the
++	 *	   length of the array of ffa_partition_info structs,
++	 *	   otherwise a negative value (error code).
++	 */
++	int (*partition_info_get)(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
++				   struct ffa_partition_info **buffer);
++};
++
++#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
++struct ffa_ops *get_ffa_ops(void);
++#else
++static inline struct ffa_ops *get_ffa_ops(void) { return NULL; }
++#endif
++
++#endif /*__LINUX_ARM_FFA_H*/
+-- 
+2.26.2
+
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 08/10] arm-bsp/linux: enable ffa driver for TC0
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (5 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 07/10] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 09/10] arm-bsp/linux: add ffa transport in optee " Arunachalam Ganapathy
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

Enables ffa driver. Sets CONFIG_ARM_FFA_TRANSPORT=y

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I71ffeb6b3bc5b28c34bfab09cdcc66227203c74c
---
 .../recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig       | 1 +
 1 file changed, 1 insertion(+)

diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig
index f858f51..0f44a94 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/defconfig
@@ -102,6 +102,7 @@ CONFIG_ARM_SCMI_CPUFREQ=y
 CONFIG_ARM_TEGRA186_CPUFREQ=y
 CONFIG_ARM_SCMI_PROTOCOL=y
 CONFIG_ARM_SCPI_PROTOCOL=y
+CONFIG_ARM_FFA_TRANSPORT=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
 CONFIG_INTEL_STRATIX10_SERVICE=y
 CONFIG_INTEL_STRATIX10_RSU=m
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 09/10] arm-bsp/linux: add ffa transport in optee driver for TC0
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (6 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 08/10] arm-bsp/linux: enable ffa driver for TC0 Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-12 15:20 ` [PATCH 10/10] arm-bsp/tc0: Enable spmd and SEL2 SPMC with optee as SEL1 SP Arunachalam Ganapathy
  2021-01-14 19:23 ` [meta-arm] [PATCH 01/10] arm: Add hafnium support Jon Mason
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

This patch adds FF-A transport driver for optee driver. This is based
on prototype version released by Arm and its port for android11-5.4-lts
kernel.

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I991895881c069767854ae8a0722cdc282b221dd9
---
 .../linux/linux-arm-platforms.inc             |    4 +
 ...for-session-s-client-UUID-generation.patch |  252 ++
 ...pport-for-session-login-client-UUID-.patch |   43 +
 ...iver-optee-Support-for-ffa-transport.patch | 3150 +++++++++++++++++
 ...m-handle-removal-in-ffa_shm_unregist.patch |   51 +
 5 files changed, 3500 insertions(+)
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
 create mode 100644 meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch

diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
index 873f120..839fe68 100644
--- a/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm-platforms.inc
@@ -77,6 +77,10 @@ SRC_URI_append_tc0 = " \
     file://0007-firmware-arm_scmi-Add-fast_switch_possible-api.patch \
     file://0008-cpufreq-arm_scmi-Set-fast_switch_possible-conditiona.patch \
     file://0009-driver-firmware-Initial-version-of-ffa-driver-based-.patch \
+    file://0010-tee-add-support-for-session-s-client-UUID-generation.patch \
+    file://0011-tee-optee-Add-support-for-session-login-client-UUID-.patch \
+    file://0012-driver-optee-Support-for-ffa-transport.patch \
+    file://0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch \
     "
 
 #
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
new file mode 100644
index 0000000..269940e
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0010-tee-add-support-for-session-s-client-UUID-generation.patch
@@ -0,0 +1,252 @@
+Upstream-Status: Backport [https://github.com/linaro-swg/linux/commit/e33bcbab16d1c0dd85d72bec275308369ad901f5#diff-317c0445401e56bde9d2ee0e0bb2758b0362a4099dca8e535dd20f1f649ecfc8]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 69a50f4234d8fb143d499e92e3f0f67009bae586 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Vesa=20J=C3=A4=C3=A4skel=C3=A4inen?=
+ <vesa.jaaskelainen@vaisala.com>
+Date: Wed, 22 Apr 2020 15:28:07 +0300
+Subject: [PATCH] tee: add support for session's client UUID generation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+TEE Client API defines that from user space only information needed for
+specified login operations is group identifier for group based logins.
+
+REE kernel is expected to formulate trustworthy client UUID and pass that
+to TEE environment. REE kernel is required to verify that provided group
+identifier for group based logins matches calling processes group
+memberships.
+
+TEE specification only defines that the information passed from REE
+environment to TEE environment is encoded into on UUID.
+
+In order to guarantee trustworthiness of client UUID user space is not
+allowed to freely pass client UUID.
+
+UUIDv5 form is used encode variable amount of information needed for
+different login types.
+
+Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
+Change-Id: I414f68d7485f95277d292fcb2646cc41bd57e62a
+---
+ drivers/tee/Kconfig     |   1 +
+ drivers/tee/tee_core.c  | 143 ++++++++++++++++++++++++++++++++++++++++
+ include/linux/tee_drv.h |  16 +++++
+ 3 files changed, 160 insertions(+)
+
+diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
+index 676ffcb64985..5a56317f3f4e 100644
+--- a/drivers/tee/Kconfig
++++ b/drivers/tee/Kconfig
+@@ -3,6 +3,7 @@
+ config TEE
+ 	tristate "Trusted Execution Environment support"
+ 	depends on HAVE_ARM_SMCCC || COMPILE_TEST
++	select CRYPTO_SHA1
+ 	select DMA_SHARED_BUFFER
+ 	select GENERIC_ALLOCATOR
+ 	help
+diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
+index 0f16d9ffd8d1..3d32a2ca48c3 100644
+--- a/drivers/tee/tee_core.c
++++ b/drivers/tee/tee_core.c
+@@ -6,18 +6,33 @@
+ #define pr_fmt(fmt) "%s: " fmt, __func__
+ 
+ #include <linux/cdev.h>
++#include <linux/cred.h>
+ #include <linux/fs.h>
+ #include <linux/idr.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/tee_drv.h>
+ #include <linux/uaccess.h>
++#include <crypto/hash.h>
++#include <crypto/sha.h>
+ #include "tee_private.h"
+ 
+ #define TEE_NUM_DEVICES	32
+ 
+ #define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
+ 
++#define TEE_UUID_NS_NAME_SIZE	128
++
++/*
++ * TEE Client UUID name space identifier (UUIDv4)
++ *
++ * Value here is random UUID that is allocated as name space identifier for
++ * forming Client UUID's for TEE environment using UUIDv5 scheme.
++ */
++static const uuid_t tee_client_uuid_ns = UUID_INIT(0x58ac9ca0, 0x2086, 0x4683,
++						   0xa1, 0xb8, 0xec, 0x4b,
++						   0xc0, 0x8e, 0x01, 0xb6);
++
+ /*
+  * Unprivileged devices in the lower half range and privileged devices in
+  * the upper half range.
+@@ -111,6 +126,134 @@ static int tee_release(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
+ 
++/**
++ * uuid_v5() - Calculate UUIDv5
++ * @uuid: Resulting UUID
++ * @ns: Name space ID for UUIDv5 function
++ * @name: Name for UUIDv5 function
++ * @size: Size of name
++ *
++ * UUIDv5 is specific in RFC 4122.
++ *
++ * This implements section (for SHA-1):
++ * 4.3.  Algorithm for Creating a Name-Based UUID
++ */
++static int uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
++		   size_t size)
++{
++	unsigned char hash[SHA1_DIGEST_SIZE];
++	struct crypto_shash *shash = NULL;
++	struct shash_desc *desc = NULL;
++	int rc;
++
++	shash = crypto_alloc_shash("sha1", 0, 0);
++	if (IS_ERR(shash)) {
++		rc = PTR_ERR(shash);
++		pr_err("shash(sha1) allocation failed\n");
++		return rc;
++	}
++
++	desc = kzalloc(sizeof(*desc) + crypto_shash_descsize(shash),
++		       GFP_KERNEL);
++	if (IS_ERR(desc)) {
++		rc = PTR_ERR(desc);
++		goto out;
++	}
++
++	desc->tfm = shash;
++
++	rc = crypto_shash_init(desc);
++	if (rc < 0)
++		goto out2;
++
++	rc = crypto_shash_update(desc, (const u8 *)ns, sizeof(*ns));
++	if (rc < 0)
++		goto out2;
++
++	rc = crypto_shash_update(desc, (const u8 *)name, size);
++	if (rc < 0)
++		goto out2;
++
++	rc = crypto_shash_final(desc, hash);
++	if (rc < 0)
++		goto out2;
++
++	memcpy(uuid->b, hash, UUID_SIZE);
++
++	/* Tag for version 5 */
++	uuid->b[6] = (hash[6] & 0x0F) | 0x50;
++	uuid->b[8] = (hash[8] & 0x3F) | 0x80;
++
++out2:
++	kfree(desc);
++
++out:
++	crypto_free_shash(shash);
++	return rc;
++}
++
++int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
++				 const u8 connection_data[TEE_IOCTL_UUID_LEN])
++{
++	const char *application_id = NULL;
++	gid_t ns_grp = (gid_t)-1;
++	kgid_t grp = INVALID_GID;
++	char *name = NULL;
++	int rc;
++
++	if (connection_method == TEE_IOCTL_LOGIN_PUBLIC) {
++		/* Nil UUID to be passed to TEE environment */
++		uuid_copy(uuid, &uuid_null);
++		return 0;
++	}
++
++	/*
++	 * In Linux environment client UUID is based on UUIDv5.
++	 *
++	 * Determine client UUID with following semantics for 'name':
++	 *
++	 * For TEEC_LOGIN_USER:
++	 * uid=<uid>
++	 *
++	 * For TEEC_LOGIN_GROUP:
++	 * gid=<gid>
++	 *
++	 */
++
++	name = kzalloc(TEE_UUID_NS_NAME_SIZE, GFP_KERNEL);
++	if (!name)
++		return -ENOMEM;
++
++	switch (connection_method) {
++	case TEE_IOCTL_LOGIN_USER:
++		scnprintf(name, TEE_UUID_NS_NAME_SIZE, "uid=%x",
++			  current_euid().val);
++		break;
++
++	case TEE_IOCTL_LOGIN_GROUP:
++		memcpy(&ns_grp, connection_data, sizeof(gid_t));
++		grp = make_kgid(current_user_ns(), ns_grp);
++		if (!gid_valid(grp) || !in_egroup_p(grp)) {
++			rc = -EPERM;
++			goto out;
++		}
++
++		scnprintf(name, TEE_UUID_NS_NAME_SIZE, "gid=%x", grp.val);
++		break;
++
++	default:
++		rc = -EINVAL;
++		goto out;
++	}
++
++	rc = uuid_v5(uuid, &tee_client_uuid_ns, name, strlen(name));
++out:
++	kfree(name);
++
++	return rc;
++}
++EXPORT_SYMBOL_GPL(tee_session_calc_client_uuid);
++
+ static int tee_ioctl_version(struct tee_context *ctx,
+ 			     struct tee_ioctl_version_data __user *uvers)
+ {
+diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
+index 7a03f68fb982..545a57f61a5e 100644
+--- a/include/linux/tee_drv.h
++++ b/include/linux/tee_drv.h
+@@ -166,6 +166,22 @@ int tee_device_register(struct tee_device *teedev);
+  */
+ void tee_device_unregister(struct tee_device *teedev);
+ 
++/**
++ * tee_session_calc_client_uuid() - Calculates client UUID for session
++ * @uuid:		Resulting UUID
++ * @connection_method:	Connection method for session (TEE_IOCTL_LOGIN_*)
++ * @connectuon_data:	Connection data for opening session
++ *
++ * Based on connection method calculates UUIDv5 based client UUID.
++ *
++ * For group based logins verifies that calling process has specified
++ * credentials.
++ *
++ * @return < 0 on failure
++ */
++int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
++				 const u8 connection_data[TEE_IOCTL_UUID_LEN]);
++
+ /**
+  * struct tee_shm - shared memory object
+  * @teedev:	device used to allocate the object
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
new file mode 100644
index 0000000..65d4311
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0011-tee-optee-Add-support-for-session-login-client-UUID-.patch
@@ -0,0 +1,43 @@
+Upstream-Status: Backport [https://github.com/linaro-swg/linux/commit/c5b4312bea5d5e5e3d4f0af640e2ef8a1c1bb167#diff-2d83bca4adf0468bdb51b155a5df495e0226f7971f4150cfffbf043fe3b5a279]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From c6c4046d8fcd34a4b8da9d844ce592951780ba8c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Vesa=20J=C3=A4=C3=A4skel=C3=A4inen?=
+ <vesa.jaaskelainen@vaisala.com>
+Date: Wed, 22 Apr 2020 15:30:39 +0300
+Subject: [PATCH] tee: optee: Add support for session login client UUID
+ generation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Adds support for client UUID generation for OP-TEE. For group based session
+logins membership is verified.
+
+Signed-off-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
+---
+ drivers/tee/optee/call.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index cf2367ba08d6..dbed3f480dc0 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -233,9 +233,13 @@ int optee_open_session(struct tee_context *ctx,
+ 	msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+ 				  OPTEE_MSG_ATTR_META;
+ 	memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
+-	memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
+ 	msg_arg->params[1].u.value.c = arg->clnt_login;
+ 
++	rc = tee_session_calc_client_uuid((uuid_t *)&msg_arg->params[1].u.value,
++					  arg->clnt_login, arg->clnt_uuid);
++	if (rc)
++		goto out;
++
+ 	rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
+ 	if (rc)
+ 		goto out;
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
new file mode 100644
index 0000000..40d4ffe
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0012-driver-optee-Support-for-ffa-transport.patch
@@ -0,0 +1,3150 @@
+Upstream-Status: Pending [https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/commit/?h=ffa_rel_proto&id=8a0acded67268b7110c69ed5425c56d881716d78]
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+
+From 2e12bf893c180cb1444ca20148983d1c45431c71 Mon Sep 17 00:00:00 2001
+From: Jens Wiklander <jens.wiklander@linaro.org>
+Date: Tue, 30 Oct 2018 21:12:11 +0100
+Subject: [PATCH] driver: optee: Support for ffa transport
+
+FF-A transport support for optee driver. Based on ffa_rel_proto at
+https://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux.git/log/?h=ffa_rel_proto
+
+Squashed in:
+    tee: remove linked list of struct tee_shm
+
+    Removes list_shm from struct tee_context since the linked list isn't used
+    any longer.
+
+    tee: remove unused tee_shm_priv_alloc()
+
+    tee_shm_priv_alloc() isn't useful in the current state and it's also not
+    not used so remove it.
+
+    tee: don't assign shm id for private shms
+
+    Private shared memory object must not be referenced from user space. To
+    guarantee that don't assign an id to keep the shared memory driver
+    private.
+
+    tee: remove redundant teedev in struct tee_shm
+
+    Since the ctx element in struct tee_shm always is valid has the teedev
+    element become redundant so remove it.
+
+    tee: add sec_world_id to struct tee_shm
+
+    Adds sec_world_id to struct tee_shm which describes a shared memory
+    object. sec_world_id can be used by a driver to store an id assigned by
+    secure world.
+
+    tee: tee_shm_op_mmap(): use TEE_SHM_USER_MAPPED
+
+    tee_shm_op_mmap() uses the TEE_SHM_USER_MAPPED flag instead of the
+    TEE_SHM_REGISTER flag to tell if a shared memory object is originating
+    from registered user space memory.
+
+    Set -Og flags for the OPTEE driver compilation.
+
+    optee: simplify optee_release()
+
+    Simplifies optee_release() with a new helper function,
+    optee_close_session_helper() which has been factored out from
+    optee_close_session().
+
+    A separate optee_release_supp() is added for the supplicant device.
+
+    tee: optee: sync optee_msg.h and optee_rpc_cmd.h
+
+    Updates to latest optee_msg.h and optee_rpc_cmd.h. There's no changes in
+    the ABI. Only some clarifications and a complete specification of RPC
+    requests where the latter is now in a separate file, optee_rpc_cmd.h.
+
+    Most of the RPC requests are not served by the OP-TEE driver instead
+    they are forwarded as opaque requests to tee-supplicant.
+
+    tee: export tee_shm_alloc()
+
+    Export tee_shm_alloc() using EXPORT_SYMBOL_GPL(). Needed by
+    optee_rng_init() and other drivers complied as a module and using OP-TEE
+    as a service.
+
+    optee: add spci support
+
+    Adds support for using SPCI as transport to the OP-TEE driver.
+
+    tee: optee: introduce SPCI specific OPTEE_MSG memref
+
+    Introduces struct optee_msg_param_smem which carries all information
+    needed when OP-TEE is calling SPCI_MEM_RETRIEVE_REQ to get the shared
+    memory reference mapped by the hypervisor in S-EL2. Register usage is
+    also updated to include the information needed.
+
+    This isn't strictly needed without a hypervisor in S-EL2 and OP-TEE
+    itself has the SPMC part. However, this is a configuration which
+    shouldn't concern normal world.
+
+    tee: optee: Use PARTITION_INFO_GET to get SP ID.
+
+    Instead of using a hardcoded partition ID for OPTEE, use the
+    SPCI_PARTITION_INFO_GET ABI to find the partition ID corresponding to
+    the OPTEE UUID.
+
+    tee: optee: Update OPTEE for mem_share SPCI
+
+    Update OPTEE to pass a scatterlist in the mem_share interface.
+
+    tee: Adapt OPTEE to new SPCI mem_share interface
+
+    optee: test_spci: Update optee, spci test driver [optee bits]
+
+    Enable optee and spci test drivesr to pass a scatterlist* and a nents
+    parameter in mem_share.
+
+    arm_spci: refactor mem_share implementation for EAC [optee bits]
+
+    arm_ffa: optee: Swap spci/SPCI for ffa/FFA. [optee bits]
+
+    arm_ffa: rename 1st member of arm_smcccv1_2_return [optee bits]
+
+    The smcccv1_2_return.func is renamed to arg0.
+
+    tee: add sec_world_id to struct tee_shm
+
+    Change the type of sec_world_id member of struct tee_shm to u64 to be
+    able to store the 64-bit Global Handle defined in FF-A.
+
+    optee: updated for FF-A 1.0
+
+    With FF-A 1.0 the ABI to secure world has changed compared to SPCI
+    beta1.
+
+    The globally unique handle to identify a shared memory object is now 64
+    bits wide instead of previous 32. The IDR in struct optee_ffa is
+    replaced with a struct rhashtable instead in order to support 64-bit
+    keys.
+
+    Register usage in the FF-A function has changed compared to SPCI beta1
+    so the OP-TEE ABI is updated accordingly. The global handle, aka cookie,
+    is now requires 2 registers.
+
+    struct optee_msg_param_smem is updated to be able to carry a 64-bit
+    global handle while maintaining the same size of the struct. Due to this
+    the "page_count" field is dropped.
+
+    optee: Update SMCC field name
+
+    optee: Update FFA_VERSION from 0.9 to 1.0
+
+    optee/call.c: Update SPCI reference to FFA
+
+Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
+Signed-off-by: Marc Bonnici <marc.bonnici@arm.com>
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+---
+ drivers/tee/Makefile              |   1 +
+ drivers/tee/optee/Makefile        |   1 +
+ drivers/tee/optee/call.c          | 318 ++++++++++---
+ drivers/tee/optee/core.c          | 735 +++++++++++++++++++++++++-----
+ drivers/tee/optee/optee_ffa.h     | 201 ++++++++
+ drivers/tee/optee/optee_msg.h     | 167 ++-----
+ drivers/tee/optee/optee_private.h |  61 ++-
+ drivers/tee/optee/optee_rpc_cmd.h | 333 ++++++++++++++
+ drivers/tee/optee/rpc.c           | 147 +++++-
+ drivers/tee/optee/shm_pool.c      |  50 ++
+ drivers/tee/optee/shm_pool.h      |   1 +
+ drivers/tee/tee_core.c            |   1 -
+ drivers/tee/tee_shm.c             |  85 +---
+ include/linux/tee_drv.h           |  26 +-
+ 14 files changed, 1710 insertions(+), 417 deletions(-)
+ create mode 100644 drivers/tee/optee/optee_ffa.h
+ create mode 100644 drivers/tee/optee/optee_rpc_cmd.h
+
+diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
+index 21f51fd88b07..c4fe9f0d3bf8 100644
+--- a/drivers/tee/Makefile
++++ b/drivers/tee/Makefile
+@@ -4,3 +4,4 @@ tee-objs += tee_core.o
+ tee-objs += tee_shm.o
+ tee-objs += tee_shm_pool.o
+ obj-$(CONFIG_OPTEE) += optee/
++ccflags-y += -Og
+diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
+index 56263ae3b1d7..57371dc91bba 100644
+--- a/drivers/tee/optee/Makefile
++++ b/drivers/tee/optee/Makefile
+@@ -6,3 +6,4 @@ optee-objs += rpc.o
+ optee-objs += supp.o
+ optee-objs += shm_pool.o
+ optee-objs += device.o
++ccflags-y += -Og
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index dbed3f480dc0..ac89ab42a43f 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -3,16 +3,20 @@
+  * Copyright (c) 2015, Linaro Limited
+  */
+ #include <linux/arm-smccc.h>
++#include <linux/arm-smcccv1_2.h>
++#include <linux/arm_ffa.h>
+ #include <linux/device.h>
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
++#include <linux/scatterlist.h>
+ #include <linux/slab.h>
+ #include <linux/tee_drv.h>
+ #include <linux/types.h>
+ #include <linux/uaccess.h>
+ #include "optee_private.h"
+ #include "optee_smc.h"
++#include "optee_ffa.h"
+ 
+ struct optee_call_waiter {
+ 	struct list_head list_node;
+@@ -122,13 +126,18 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
+  *
+  * Returns return code from secure world, 0 is OK
+  */
+-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
++int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
+ {
+ 	struct optee *optee = tee_get_drvdata(ctx->teedev);
+-	struct optee_call_waiter w;
++	struct optee_call_waiter w = { };
+ 	struct optee_rpc_param param = { };
+ 	struct optee_call_ctx call_ctx = { };
+-	u32 ret;
++	phys_addr_t parg = 0;
++	int rc = 0;
++
++	rc = tee_shm_get_pa(arg, 0, &parg);
++	if (rc)
++		return rc;
+ 
+ 	param.a0 = OPTEE_SMC_CALL_WITH_ARG;
+ 	reg_pair_from_64(&param.a1, &param.a2, parg);
+@@ -155,7 +164,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+ 			param.a3 = res.a3;
+ 			optee_handle_rpc(ctx, &param, &call_ctx);
+ 		} else {
+-			ret = res.a0;
++			rc = res.a0;
+ 			break;
+ 		}
+ 	}
+@@ -167,16 +176,15 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+ 	 */
+ 	optee_cq_wait_final(&optee->call_queue, &w);
+ 
+-	return ret;
++	return rc;
+ }
+ 
+ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+-				   struct optee_msg_arg **msg_arg,
+-				   phys_addr_t *msg_parg)
++				   struct optee_msg_arg **msg_arg)
+ {
+-	int rc;
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *ma;
++	int rc = 0;
++	struct tee_shm *shm = NULL;
++	struct optee_msg_arg *ma = NULL;
+ 
+ 	shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
+ 			    TEE_SHM_MAPPED);
+@@ -189,10 +197,6 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+ 		goto out;
+ 	}
+ 
+-	rc = tee_shm_get_pa(shm, 0, msg_parg);
+-	if (rc)
+-		goto out;
+-
+ 	memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+ 	ma->num_params = num_params;
+ 	*msg_arg = ma;
+@@ -209,15 +213,15 @@ int optee_open_session(struct tee_context *ctx,
+ 		       struct tee_ioctl_open_session_arg *arg,
+ 		       struct tee_param *param)
+ {
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
+ 	struct optee_context_data *ctxdata = ctx->data;
+-	int rc;
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *msg_arg;
+-	phys_addr_t msg_parg;
++	struct optee_msg_arg *msg_arg = NULL;
+ 	struct optee_session *sess = NULL;
++	struct tee_shm *shm = NULL;
++	int rc = 0;
+ 
+ 	/* +2 for the meta parameters added below */
+-	shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
++	shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
+ 	if (IS_ERR(shm))
+ 		return PTR_ERR(shm);
+ 
+@@ -240,7 +244,8 @@ int optee_open_session(struct tee_context *ctx,
+ 	if (rc)
+ 		goto out;
+ 
+-	rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
++	rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
++				      arg->num_params, param);
+ 	if (rc)
+ 		goto out;
+ 
+@@ -250,7 +255,7 @@ int optee_open_session(struct tee_context *ctx,
+ 		goto out;
+ 	}
+ 
+-	if (optee_do_call_with_arg(ctx, msg_parg)) {
++	if (optee->ops->do_call_with_arg(ctx, shm)) {
+ 		msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ 		msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ 	}
+@@ -265,7 +270,8 @@ int optee_open_session(struct tee_context *ctx,
+ 		kfree(sess);
+ 	}
+ 
+-	if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
++	if (optee->ops->from_msg_param(optee, param, arg->num_params,
++				       msg_arg->params + 2)) {
+ 		arg->ret = TEEC_ERROR_COMMUNICATION;
+ 		arg->ret_origin = TEEC_ORIGIN_COMMS;
+ 		/* Close session again to avoid leakage */
+@@ -281,12 +287,28 @@ int optee_open_session(struct tee_context *ctx,
+ 	return rc;
+ }
+ 
+-int optee_close_session(struct tee_context *ctx, u32 session)
++int optee_close_session_helper(struct tee_context *ctx, u32 session)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	struct optee_msg_arg *msg_arg = NULL;
++	struct tee_shm *shm = NULL;
++
++	shm = get_msg_arg(ctx, 0, &msg_arg);
++	if (IS_ERR(shm))
++		return PTR_ERR(shm);
++
++	msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
++	msg_arg->session = session;
++	optee->ops->do_call_with_arg(ctx, shm);
++
++	tee_shm_free(shm);
++
++	return 0;
++}
++
++static int remove_session(struct tee_context *ctx, u32 session)
+ {
+ 	struct optee_context_data *ctxdata = ctx->data;
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *msg_arg;
+-	phys_addr_t msg_parg;
+ 	struct optee_session *sess;
+ 
+ 	/* Check that the session is valid and remove it from the list */
+@@ -299,27 +321,28 @@ int optee_close_session(struct tee_context *ctx, u32 session)
+ 		return -EINVAL;
+ 	kfree(sess);
+ 
+-	shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+-	if (IS_ERR(shm))
+-		return PTR_ERR(shm);
++	return 0;
++}
+ 
+-	msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+-	msg_arg->session = session;
+-	optee_do_call_with_arg(ctx, msg_parg);
++int optee_close_session(struct tee_context *ctx, u32 session)
++{
++	int rc = remove_session(ctx, session);
+ 
+-	tee_shm_free(shm);
+-	return 0;
++	if (rc)
++		return rc;
++
++	return optee_close_session_helper(ctx, session);
+ }
+ 
+ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ 		      struct tee_param *param)
+ {
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
+ 	struct optee_context_data *ctxdata = ctx->data;
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *msg_arg;
+-	phys_addr_t msg_parg;
+-	struct optee_session *sess;
+-	int rc;
++	struct optee_msg_arg *msg_arg = NULL;
++	struct optee_session *sess = NULL;
++	struct tee_shm *shm = NULL;
++	int rc = 0;
+ 
+ 	/* Check that the session is valid */
+ 	mutex_lock(&ctxdata->mutex);
+@@ -328,7 +351,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ 	if (!sess)
+ 		return -EINVAL;
+ 
+-	shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
++	shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
+ 	if (IS_ERR(shm))
+ 		return PTR_ERR(shm);
+ 	msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+@@ -336,16 +359,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ 	msg_arg->session = arg->session;
+ 	msg_arg->cancel_id = arg->cancel_id;
+ 
+-	rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
++	rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
++				      param);
+ 	if (rc)
+ 		goto out;
+ 
+-	if (optee_do_call_with_arg(ctx, msg_parg)) {
++	if (optee->ops->do_call_with_arg(ctx, shm)) {
+ 		msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ 		msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ 	}
+ 
+-	if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
++	if (optee->ops->from_msg_param(optee, param, arg->num_params,
++				       msg_arg->params)) {
+ 		msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+ 		msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+ 	}
+@@ -359,11 +384,11 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ 
+ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+ {
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
+ 	struct optee_context_data *ctxdata = ctx->data;
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *msg_arg;
+-	phys_addr_t msg_parg;
+-	struct optee_session *sess;
++	struct optee_msg_arg *msg_arg = NULL;
++	struct optee_session *sess = NULL;
++	struct tee_shm *shm = NULL;
+ 
+ 	/* Check that the session is valid */
+ 	mutex_lock(&ctxdata->mutex);
+@@ -372,14 +397,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+ 	if (!sess)
+ 		return -EINVAL;
+ 
+-	shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
++	shm = get_msg_arg(ctx, 0, &msg_arg);
+ 	if (IS_ERR(shm))
+ 		return PTR_ERR(shm);
+ 
+ 	msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
+ 	msg_arg->session = session;
+ 	msg_arg->cancel_id = cancel_id;
+-	optee_do_call_with_arg(ctx, msg_parg);
++	optee->ops->do_call_with_arg(ctx, shm);
+ 
+ 	tee_shm_free(shm);
+ 	return 0;
+@@ -442,6 +467,16 @@ void optee_disable_shm_cache(struct optee *optee)
+ 	optee_cq_wait_final(&optee->call_queue, &w);
+ }
+ 
++/**
++ * optee_ffa_disable_shm_cache() - Disables caching of some shared memory
++ *                                  allocation in OP-TEE
++ * @optee:	main service struct
++ */
++void optee_ffa_disable_shm_cache(struct optee *optee)
++{
++	BUG();
++}
++
+ #define PAGELIST_ENTRIES_PER_PAGE				\
+ 	((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
+ 
+@@ -577,11 +612,11 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ 		       struct page **pages, size_t num_pages,
+ 		       unsigned long start)
+ {
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	struct optee_msg_arg *msg_arg = NULL;
+ 	struct tee_shm *shm_arg = NULL;
+-	struct optee_msg_arg *msg_arg;
+-	u64 *pages_list;
+-	phys_addr_t msg_parg;
+-	int rc;
++	u64 *pages_list = NULL;
++	int rc = 0;
+ 
+ 	if (!num_pages)
+ 		return -EINVAL;
+@@ -594,7 +629,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ 	if (!pages_list)
+ 		return -ENOMEM;
+ 
+-	shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
++	shm_arg = get_msg_arg(ctx, 1, &msg_arg);
+ 	if (IS_ERR(shm_arg)) {
+ 		rc = PTR_ERR(shm_arg);
+ 		goto out;
+@@ -615,7 +650,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ 	msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
+ 	  (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
+ 
+-	if (optee_do_call_with_arg(ctx, msg_parg) ||
++	if (optee->ops->do_call_with_arg(ctx, shm) ||
+ 	    msg_arg->ret != TEEC_SUCCESS)
+ 		rc = -EINVAL;
+ 
+@@ -627,12 +662,12 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
+ 
+ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
+ {
+-	struct tee_shm *shm_arg;
+-	struct optee_msg_arg *msg_arg;
+-	phys_addr_t msg_parg;
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	struct optee_msg_arg *msg_arg = NULL;
++	struct tee_shm *shm_arg = NULL;
+ 	int rc = 0;
+ 
+-	shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
++	shm_arg = get_msg_arg(ctx, 1, &msg_arg);
+ 	if (IS_ERR(shm_arg))
+ 		return PTR_ERR(shm_arg);
+ 
+@@ -641,7 +676,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
+ 	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+ 	msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
+ 
+-	if (optee_do_call_with_arg(ctx, msg_parg) ||
++	if (optee->ops->do_call_with_arg(ctx, shm) ||
+ 	    msg_arg->ret != TEEC_SUCCESS)
+ 		rc = -EINVAL;
+ 	tee_shm_free(shm_arg);
+@@ -663,3 +698,166 @@ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm)
+ {
+ 	return 0;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static int optee_ffa_yielding_call(struct tee_context *ctx, u32 w3, u32 w4,
++				    u32 w5)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	struct arm_smcccv1_2_return ret = { };
++	const u32 dst = optee->ffa.dst;
++	struct optee_call_waiter w;
++	u32 w6 = 0;
++	u32 w7 = 0;
++	int rc = 0;
++
++	/* Initialize waiter */
++	optee_cq_wait_init(&optee->call_queue, &w);
++	while (true) {
++		ret = optee->ffa.ops->sync_msg_send(dst, w3, w4, w5, w6, w7);
++
++		if (ret.arg0) {
++			pr_err("ret.arg0 %d\n", (int)ret.arg0);
++			rc = -EIO;
++			goto done;
++		}
++
++		switch ((int)ret.arg3) {
++		case FFA_SUCCESS:
++			break;
++		case FFA_BUSY:
++			if (w3 == OPTEE_FFA_YIELDING_CALL_RESUME) {
++				pr_err("err OPTEE_FFA_YIELDING_CALL_RESUME\n");
++				rc = -EIO;
++				goto done;
++			}
++
++			/*
++			 * Out of threads in secure world, wait for a thread
++			 * become available.
++			 */
++			optee_cq_wait_for_completion(&optee->call_queue, &w);
++			continue;
++		default:
++			pr_err("ret.arg3 0x%llx\n", (u64)ret.arg3);
++			rc = -EIO;
++			goto done;
++		}
++
++		if (ret.arg4 == OPTEE_FFA_YIELDING_CALL_RETURN_DONE)
++			goto done;
++
++		might_sleep();
++		w4 = ret.arg4;
++		w5 = ret.arg5;
++		w6 = ret.arg6;
++		optee_handle_ffa_rpc(ctx, &w4, &w5, &w6);
++		w3 = OPTEE_FFA_YIELDING_CALL_RESUME;
++		w7 = ret.arg7;
++	}
++done:
++
++	/*
++	 * We're done with our thread in secure world, if there's any
++	 * thread waiters wake up one.
++	 */
++	optee_cq_wait_final(&optee->call_queue, &w);
++
++	return rc;
++}
++
++int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *shm)
++{
++	if (shm->offset)
++		return -EINVAL;
++	return optee_ffa_yielding_call(ctx, OPTEE_FFA_YIELDING_CALL_WITH_ARG,
++				       shm->sec_world_id,
++				       shm->sec_world_id >> 32);
++}
++
++int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
++			    struct page **pages, size_t num_pages,
++			    unsigned long start)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	u64 global_handle = 0;
++	u32 rc = 0;
++	struct sg_table sgt;
++	struct ffa_mem_region_attributes mem_attr = {
++		.receiver = optee->ffa.dst,
++		.attrs = FFA_MEM_RW,
++	};
++
++	rc = check_mem_type(start, num_pages);
++	if (rc)
++		return rc;
++
++	sg_alloc_table_from_pages(&sgt, pages,
++			      num_pages, 0,
++			      num_pages * 4096, GFP_KERNEL);
++
++	rc = optee->ffa.ops->mem_share(0, 0, &mem_attr, 1, sgt.sgl, sgt.nents,
++		&global_handle, true);
++	if (rc) {
++		if (rc == FFA_NO_MEMORY)
++			return -ENOMEM;
++		return -EINVAL;
++	}
++
++	rc = optee_shm_add_ffa_handle(optee, shm, global_handle);
++	if (rc) {
++		optee->ffa.ops->mem_reclaim(global_handle, 0);
++		return rc;
++	}
++
++	shm->sec_world_id = global_handle;
++
++	return 0;
++}
++
++int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	u64 global_handle = shm->sec_world_id;
++	int rc = 0;
++
++	optee_shm_rem_ffa_handle(optee, global_handle);
++	shm->sec_world_id = 0;
++
++	rc = optee_ffa_yielding_call(ctx,
++				     OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM,
++				     global_handle, global_handle >> 32);
++	if (rc)
++		pr_err("OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM id 0x%llx rc %d\n",
++		       global_handle, rc);
++
++	rc = optee->ffa.ops->mem_reclaim(global_handle, 0);
++	if (rc)
++		pr_err("mem_reclain: %d", rc);
++
++	return rc;
++}
++
++int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
++				   struct tee_shm *shm)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	int rc = 0;
++
++	/*
++	 * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
++	 * since this is OP-TEE freeing via RPC so it has already retired
++	 * this ID.
++	 */
++
++	rc = optee->ffa.ops->mem_reclaim(shm->sec_world_id, 0);
++	if (rc)
++		pr_err("mem_reclain: %d", rc);
++
++	optee_shm_rem_ffa_handle(optee, shm->sec_world_id);
++
++	shm->sec_world_id = 0;
++
++	return rc;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
+index b830e0a87fba..4178ae7f914a 100644
+--- a/drivers/tee/optee/core.c
++++ b/drivers/tee/optee/core.c
+@@ -6,6 +6,8 @@
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+ 
+ #include <linux/arm-smccc.h>
++#include <linux/arm-smcccv1_2.h>
++#include <linux/arm_ffa.h>
+ #include <linux/errno.h>
+ #include <linux/io.h>
+ #include <linux/module.h>
+@@ -19,12 +21,157 @@
+ #include <linux/uaccess.h>
+ #include "optee_private.h"
+ #include "optee_smc.h"
++#include "optee_ffa.h"
+ #include "shm_pool.h"
+ 
+ #define DRIVER_NAME "optee"
++#define SUPPORTED_OPTEE_PARTITIONS 1
+ 
+ #define OPTEE_SHM_NUM_PRIV_PAGES	CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
+ 
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++struct shm_rhash {
++	struct tee_shm *shm;
++	u64 global_id;
++	struct rhash_head linkage;
++};
++
++static void rh_free_fn(void *ptr, void *arg)
++{
++	kfree(ptr);
++}
++
++static const struct rhashtable_params shm_rhash_params = {
++	.head_offset = offsetof(struct shm_rhash, linkage),
++	.key_len     = sizeof(u64),
++	.key_offset  = offsetof(struct shm_rhash, global_id),
++	.automatic_shrinking = true,
++};
++
++struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id)
++{
++	struct shm_rhash *r = NULL;
++	struct tee_shm *shm = NULL;
++
++	mutex_lock(&optee->ffa.mutex);
++	r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
++				   shm_rhash_params);
++	if (r)
++		shm = r->shm;
++	mutex_unlock(&optee->ffa.mutex);
++
++	return shm;
++}
++
++int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
++			      u64 global_id)
++{
++	struct shm_rhash *r = NULL;
++	int rc = 0;
++
++	r = kmalloc(sizeof(*r), GFP_KERNEL);
++	if (!r)
++		return -ENOMEM;
++	r->shm = shm;
++	r->global_id = global_id;
++
++	mutex_lock(&optee->ffa.mutex);
++	rc = rhashtable_lookup_insert_fast(&optee->ffa.global_ids, &r->linkage,
++					   shm_rhash_params);
++	mutex_unlock(&optee->ffa.mutex);
++
++	if (rc)
++		kfree(r);
++
++	return rc;
++}
++
++int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id)
++{
++	struct shm_rhash *r = NULL;
++	int rc = -ENOENT;
++
++	mutex_lock(&optee->ffa.mutex);
++	r = rhashtable_lookup_fast(&optee->ffa.global_ids, &global_id,
++				   shm_rhash_params);
++	if (r) {
++		rc = rhashtable_remove_fast(&optee->ffa.global_ids,
++					    &r->linkage, shm_rhash_params);
++		if (!rc)
++			kfree(r);
++	}
++	mutex_unlock(&optee->ffa.mutex);
++
++	return rc;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
++static void from_msg_param_value(struct tee_param *p, u32 attr,
++				 const struct optee_msg_param *mp)
++{
++	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
++		  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
++	p->u.value.a = mp->u.value.a;
++	p->u.value.b = mp->u.value.b;
++	p->u.value.c = mp->u.value.c;
++}
++
++static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
++				  const struct optee_msg_param *mp)
++{
++	struct tee_shm *shm = NULL;
++	phys_addr_t pa = 0;
++	int rc = 0;
++
++	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++		  attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
++	p->u.memref.size = mp->u.tmem.size;
++	shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
++	if (!shm) {
++		p->u.memref.shm_offs = 0;
++		p->u.memref.shm = NULL;
++		return 0;
++	}
++
++	rc = tee_shm_get_pa(shm, 0, &pa);
++	if (rc)
++		return rc;
++
++	p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
++	p->u.memref.shm = shm;
++
++	/* Check that the memref is covered by the shm object */
++	if (p->u.memref.size) {
++		size_t o = p->u.memref.shm_offs +
++			   p->u.memref.size - 1;
++
++		rc = tee_shm_get_pa(shm, o, NULL);
++		if (rc)
++			return rc;
++	}
++
++	return 0;
++}
++
++static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
++				   const struct optee_msg_param *mp)
++{
++	struct tee_shm *shm = NULL;
++
++	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++		  attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
++	p->u.memref.size = mp->u.rmem.size;
++	shm = (struct tee_shm *)(unsigned long) mp->u.rmem.shm_ref;
++
++	if (shm) {
++		p->u.memref.shm_offs = mp->u.rmem.offs;
++		p->u.memref.shm = shm;
++	} else {
++		p->u.memref.shm_offs = 0;
++		p->u.memref.shm = NULL;
++	}
++}
++
+ /**
+  * optee_from_msg_param() - convert from OPTEE_MSG parameters to
+  *			    struct tee_param
+@@ -33,13 +180,12 @@
+  * @msg_params:	OPTEE_MSG parameters
+  * Returns 0 on success or <0 on failure
+  */
+-int optee_from_msg_param(struct tee_param *params, size_t num_params,
+-			 const struct optee_msg_param *msg_params)
++static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
++				size_t num_params,
++				const struct optee_msg_param *msg_params)
+ {
+-	int rc;
+-	size_t n;
+-	struct tee_shm *shm;
+-	phys_addr_t pa;
++	size_t n = 0;
++	int rc = 0;
+ 
+ 	for (n = 0; n < num_params; n++) {
+ 		struct tee_param *p = params + n;
+@@ -54,58 +200,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+-			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+-				  attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+-			p->u.value.a = mp->u.value.a;
+-			p->u.value.b = mp->u.value.b;
+-			p->u.value.c = mp->u.value.c;
++			from_msg_param_value(p, attr, mp);
+ 			break;
+ 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+-			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+-				  attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+-			p->u.memref.size = mp->u.tmem.size;
+-			shm = (struct tee_shm *)(unsigned long)
+-				mp->u.tmem.shm_ref;
+-			if (!shm) {
+-				p->u.memref.shm_offs = 0;
+-				p->u.memref.shm = NULL;
+-				break;
+-			}
+-			rc = tee_shm_get_pa(shm, 0, &pa);
++			rc = from_msg_param_tmp_mem(p, attr, mp);
+ 			if (rc)
+ 				return rc;
+-			p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+-			p->u.memref.shm = shm;
+-
+-			/* Check that the memref is covered by the shm object */
+-			if (p->u.memref.size) {
+-				size_t o = p->u.memref.shm_offs +
+-					   p->u.memref.size - 1;
+-
+-				rc = tee_shm_get_pa(shm, o, NULL);
+-				if (rc)
+-					return rc;
+-			}
+ 			break;
+ 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
+ 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
+-			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+-				  attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+-			p->u.memref.size = mp->u.rmem.size;
+-			shm = (struct tee_shm *)(unsigned long)
+-				mp->u.rmem.shm_ref;
+-
+-			if (!shm) {
+-				p->u.memref.shm_offs = 0;
+-				p->u.memref.shm = NULL;
+-				break;
+-			}
+-			p->u.memref.shm_offs = mp->u.rmem.offs;
+-			p->u.memref.shm = shm;
+-
++			from_msg_param_reg_mem(p, attr, mp);
+ 			break;
+ 
+ 		default:
+@@ -115,11 +222,21 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
+ 	return 0;
+ }
+ 
++static void to_msg_param_value(struct optee_msg_param *mp,
++			       const struct tee_param *p)
++{
++	mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
++		   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
++	mp->u.value.a = p->u.value.a;
++	mp->u.value.b = p->u.value.b;
++	mp->u.value.c = p->u.value.c;
++}
++
+ static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
+ 				const struct tee_param *p)
+ {
+-	int rc;
+-	phys_addr_t pa;
++	phys_addr_t pa = 0;
++	int rc = 0;
+ 
+ 	mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT + p->attr -
+ 		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+@@ -162,11 +279,12 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
+  * @params:	subsystem itnernal parameter representation
+  * Returns 0 on success or <0 on failure
+  */
+-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+-		       const struct tee_param *params)
++static int optee_to_msg_param(struct optee *optee,
++			      struct optee_msg_param *msg_params,
++			      size_t num_params, const struct tee_param *params)
+ {
+-	int rc;
+-	size_t n;
++	size_t n = 0;
++	int rc = 0;
+ 
+ 	for (n = 0; n < num_params; n++) {
+ 		const struct tee_param *p = params + n;
+@@ -180,11 +298,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+ 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+ 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+ 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+-			mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+-				   TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+-			mp->u.value.a = p->u.value.a;
+-			mp->u.value.b = p->u.value.b;
+-			mp->u.value.c = p->u.value.c;
++			to_msg_param_value(mp, p);
+ 			break;
+ 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+ 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+@@ -203,6 +317,137 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static void from_msg_param_ffa_mem(struct optee *optee, struct tee_param *p,
++				    u32 attr, const struct optee_msg_param *mp)
++{
++	struct tee_shm *shm = NULL;
++	u64 offs_high = 0;
++	u64 offs_low = 0;
++
++	p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
++		  attr - OPTEE_MSG_ATTR_TYPE_SMEM_INPUT;
++	p->u.memref.size = mp->u.smem.size;
++	shm = optee_shm_from_ffa_handle(optee, mp->u.smem.global_id);
++	p->u.memref.shm = shm;
++	if (shm) {
++		offs_low = mp->u.smem.offs_low;
++		offs_high = mp->u.smem.offs_high;
++	}
++	p->u.memref.shm_offs = offs_low | offs_high << 32;
++}
++
++/**
++ * optee_ffa_from_msg_param() - convert from OPTEE_MSG parameters to
++ *				 struct tee_param
++ * @params:	subsystem internal parameter representation
++ * @num_params:	number of elements in the parameter arrays
++ * @msg_params:	OPTEE_MSG parameters
++ * Returns 0 on success or <0 on failure
++ */
++static int optee_ffa_from_msg_param(struct optee *optee,
++				     struct tee_param *params,
++				     size_t num_params,
++				     const struct optee_msg_param *msg_params)
++{
++	size_t n = 0;
++
++	for (n = 0; n < num_params; n++) {
++		struct tee_param *p = params + n;
++		const struct optee_msg_param *mp = msg_params + n;
++		u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
++
++		switch (attr) {
++		case OPTEE_MSG_ATTR_TYPE_NONE:
++			p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
++			memset(&p->u, 0, sizeof(p->u));
++			break;
++		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
++		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
++		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
++			from_msg_param_value(p, attr, mp);
++			break;
++		case OPTEE_MSG_ATTR_TYPE_SMEM_INPUT:
++		case OPTEE_MSG_ATTR_TYPE_SMEM_OUTPUT:
++		case OPTEE_MSG_ATTR_TYPE_SMEM_INOUT:
++			from_msg_param_ffa_mem(optee, p, attr, mp);
++			break;
++		default:
++			return -EINVAL;
++		}
++	}
++	return 0;
++}
++
++static int to_msg_param_ffa_mem(struct optee_msg_param *mp,
++				 const struct tee_param *p)
++{
++	struct tee_shm *shm = p->u.memref.shm;
++
++	mp->attr = OPTEE_MSG_ATTR_TYPE_SMEM_INPUT + p->attr -
++		   TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
++
++	if (shm) {
++		u64 shm_offs = p->u.memref.shm_offs;
++
++		mp->u.smem.internal_offs = shm->offset;
++
++		mp->u.smem.offs_low = shm_offs;
++		mp->u.smem.offs_high = shm_offs >> 32;
++		/* Check that the entire offset could be stored. */
++		if (mp->u.smem.offs_high != shm_offs >> 32)
++			return -EINVAL;
++
++		mp->u.smem.global_id = shm->sec_world_id;
++	} else {
++		memset(&mp->u, 0, sizeof(mp->u));
++	}
++	mp->u.smem.size = p->u.memref.size;
++	return 0;
++}
++
++/**
++ * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
++ * @msg_params:	OPTEE_MSG parameters
++ * @num_params:	number of elements in the parameter arrays
++ * @params:	subsystem itnernal parameter representation
++ * Returns 0 on success or <0 on failure
++ */
++static int optee_ffa_to_msg_param(struct optee *optee,
++				   struct optee_msg_param *msg_params,
++				   size_t num_params,
++				   const struct tee_param *params)
++{
++	size_t n;
++
++	for (n = 0; n < num_params; n++) {
++		const struct tee_param *p = params + n;
++		struct optee_msg_param *mp = msg_params + n;
++
++		switch (p->attr) {
++		case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
++			mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
++			memset(&mp->u, 0, sizeof(mp->u));
++			break;
++		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
++		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
++		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
++			to_msg_param_value(mp, p);
++			break;
++		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
++		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
++		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
++			if (to_msg_param_ffa_mem(mp, p))
++				return -EINVAL;
++			break;
++		default:
++			return -EINVAL;
++		}
++	}
++	return 0;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
+ static void optee_get_version(struct tee_device *teedev,
+ 			      struct tee_ioctl_version_data *vers)
+ {
+@@ -218,6 +463,17 @@ static void optee_get_version(struct tee_device *teedev,
+ 	*vers = v;
+ }
+ 
++static void optee_ffa_get_version(struct tee_device *teedev,
++				   struct tee_ioctl_version_data *vers)
++{
++	struct tee_ioctl_version_data v = {
++		.impl_id = TEE_IMPL_ID_OPTEE,
++		.impl_caps = TEE_OPTEE_CAP_TZ,
++		.gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
++	};
++	*vers = v;
++}
++
+ static int optee_open(struct tee_context *ctx)
+ {
+ 	struct optee_context_data *ctxdata;
+@@ -250,57 +506,41 @@ static int optee_open(struct tee_context *ctx)
+ 	return 0;
+ }
+ 
+-static void optee_release(struct tee_context *ctx)
++static void optee_release_helper(struct tee_context *ctx,
++				 int (*close_session)(struct tee_context *ctx,
++						      u32 session))
+ {
+ 	struct optee_context_data *ctxdata = ctx->data;
+-	struct tee_device *teedev = ctx->teedev;
+-	struct optee *optee = tee_get_drvdata(teedev);
+-	struct tee_shm *shm;
+-	struct optee_msg_arg *arg = NULL;
+-	phys_addr_t parg;
+ 	struct optee_session *sess;
+ 	struct optee_session *sess_tmp;
+ 
+ 	if (!ctxdata)
+ 		return;
+ 
+-	shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
+-	if (!IS_ERR(shm)) {
+-		arg = tee_shm_get_va(shm, 0);
+-		/*
+-		 * If va2pa fails for some reason, we can't call into
+-		 * secure world, only free the memory. Secure OS will leak
+-		 * sessions and finally refuse more sessions, but we will
+-		 * at least let normal world reclaim its memory.
+-		 */
+-		if (!IS_ERR(arg))
+-			if (tee_shm_va2pa(shm, arg, &parg))
+-				arg = NULL; /* prevent usage of parg below */
+-	}
+-
+ 	list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
+ 				 list_node) {
+ 		list_del(&sess->list_node);
+-		if (!IS_ERR_OR_NULL(arg)) {
+-			memset(arg, 0, sizeof(*arg));
+-			arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+-			arg->session = sess->session_id;
+-			optee_do_call_with_arg(ctx, parg);
+-		}
++		close_session(ctx, sess->session_id);
+ 		kfree(sess);
+ 	}
+ 	kfree(ctxdata);
++	ctx->data = NULL;
++}
+ 
+-	if (!IS_ERR(shm))
+-		tee_shm_free(shm);
++static void optee_release(struct tee_context *ctx)
++{
++	optee_release_helper(ctx, optee_close_session_helper);
++}
+ 
+-	ctx->data = NULL;
++static void optee_release_supp(struct tee_context *ctx)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
+ 
+-	if (teedev == optee->supp_teedev)
+-		optee_supp_release(&optee->supp);
++	optee_release_helper(ctx, optee_close_session_helper);
++	optee_supp_release(&optee->supp);
+ }
+ 
+-static const struct tee_driver_ops optee_ops = {
++static const struct tee_driver_ops optee_legacy_clnt_ops = {
+ 	.get_version = optee_get_version,
+ 	.open = optee_open,
+ 	.release = optee_release,
+@@ -312,29 +552,36 @@ static const struct tee_driver_ops optee_ops = {
+ 	.shm_unregister = optee_shm_unregister,
+ };
+ 
+-static const struct tee_desc optee_desc = {
+-	.name = DRIVER_NAME "-clnt",
+-	.ops = &optee_ops,
++static const struct tee_desc optee_legacy_clnt_desc = {
++	.name = DRIVER_NAME "legacy-clnt",
++	.ops = &optee_legacy_clnt_ops,
+ 	.owner = THIS_MODULE,
+ };
+ 
+-static const struct tee_driver_ops optee_supp_ops = {
++static const struct tee_driver_ops optee_legacy_supp_ops = {
+ 	.get_version = optee_get_version,
+ 	.open = optee_open,
+-	.release = optee_release,
++	.release = optee_release_supp,
+ 	.supp_recv = optee_supp_recv,
+ 	.supp_send = optee_supp_send,
+ 	.shm_register = optee_shm_register_supp,
+ 	.shm_unregister = optee_shm_unregister_supp,
+ };
+ 
+-static const struct tee_desc optee_supp_desc = {
+-	.name = DRIVER_NAME "-supp",
+-	.ops = &optee_supp_ops,
++static const struct tee_desc optee_legacy_supp_desc = {
++	.name = DRIVER_NAME "legacy-supp",
++	.ops = &optee_legacy_supp_ops,
+ 	.owner = THIS_MODULE,
+ 	.flags = TEE_DESC_PRIVILEGED,
+ };
+ 
++static const struct optee_ops optee_legacy_ops = {
++	.do_call_with_arg = optee_do_call_with_arg,
++	.to_msg_param = optee_to_msg_param,
++	.from_msg_param = optee_from_msg_param,
++};
++
++
+ static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
+ {
+ 	struct arm_smccc_res res;
+@@ -534,16 +781,9 @@ static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
+ 	arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+ }
+ 
+-static optee_invoke_fn *get_invoke_func(struct device_node *np)
++static optee_invoke_fn *get_invoke_func(const char *method)
+ {
+-	const char *method;
+ 
+-	pr_info("probing for conduit method from DT.\n");
+-
+-	if (of_property_read_string(np, "method", &method)) {
+-		pr_warn("missing \"method\" property\n");
+-		return ERR_PTR(-ENXIO);
+-	}
+ 
+ 	if (!strcmp("hvc", method))
+ 		return optee_smccc_hvc;
+@@ -554,7 +794,7 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np)
+ 	return ERR_PTR(-EINVAL);
+ }
+ 
+-static struct optee *optee_probe(struct device_node *np)
++static struct optee *optee_probe_legacy(const char *method)
+ {
+ 	optee_invoke_fn *invoke_fn;
+ 	struct tee_shm_pool *pool = ERR_PTR(-EINVAL);
+@@ -564,7 +804,7 @@ static struct optee *optee_probe(struct device_node *np)
+ 	u32 sec_caps;
+ 	int rc;
+ 
+-	invoke_fn = get_invoke_func(np);
++	invoke_fn = get_invoke_func(method);
+ 	if (IS_ERR(invoke_fn))
+ 		return (void *)invoke_fn;
+ 
+@@ -606,17 +846,18 @@ static struct optee *optee_probe(struct device_node *np)
+ 		goto err;
+ 	}
+ 
++	optee->ops = &optee_legacy_ops;
+ 	optee->invoke_fn = invoke_fn;
+ 	optee->sec_caps = sec_caps;
+ 
+-	teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
++	teedev = tee_device_alloc(&optee_legacy_clnt_desc, NULL, pool, optee);
+ 	if (IS_ERR(teedev)) {
+ 		rc = PTR_ERR(teedev);
+ 		goto err;
+ 	}
+ 	optee->teedev = teedev;
+ 
+-	teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
++	teedev = tee_device_alloc(&optee_legacy_supp_desc, NULL, pool, optee);
+ 	if (IS_ERR(teedev)) {
+ 		rc = PTR_ERR(teedev);
+ 		goto err;
+@@ -662,6 +903,266 @@ static struct optee *optee_probe(struct device_node *np)
+ 	return ERR_PTR(rc);
+ }
+ 
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static bool optee_ffa_api_is_compatbile(struct ffa_ops *ffa_ops, u32 dst)
++{
++	struct arm_smcccv1_2_return ret = { };
++
++	ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_GET_API_VERSION,
++				     0, 0, 0, 0);
++	if (ret.arg0 != FFA_SUCCESS) {
++		pr_err("Unexpected return fid 0x%llx", ret.arg0);
++		return false;
++	}
++	if (ret.arg3 != OPTEE_FFA_VERSION_MAJOR ||
++	    ret.arg4 < OPTEE_FFA_VERSION_MINOR) {
++		pr_err("Incompatible OP-TEE API version %llu.%llu",
++		       ret.arg3, ret.arg4);
++		return false;
++	}
++
++	ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_GET_OS_VERSION,
++				     0, 0, 0, 0);
++	if (ret.arg0) {
++		pr_err("Unexpected error 0x%llx", ret.arg0);
++		return false;
++	}
++	if (ret.arg5)
++		pr_info("revision %llu.%llu (%08llx)",
++			ret.arg3, ret.arg4, ret.arg5);
++	else
++		pr_info("revision %llu.%llu", ret.arg3, ret.arg4);
++
++	return true;
++}
++
++static bool optee_ffa_exchange_caps(struct ffa_ops *ffa_ops, u32 dst,
++				     u32 *sec_caps)
++{
++	struct arm_smcccv1_2_return ret = { };
++
++	ret = ffa_ops->sync_msg_send(dst, OPTEE_FFA_EXCHANGE_CAPABILITIES,
++				     0, 0, 0, 0);
++	if (ret.arg0) {
++		pr_err("Unexpected error 0x%llx", ret.arg0);
++		return false;
++	}
++
++	*sec_caps = 0;
++
++	return true;
++}
++
++static struct tee_shm_pool *optee_ffa_config_dyn_shm(void)
++{
++	struct tee_shm_pool_mgr *priv_mgr;
++	struct tee_shm_pool_mgr *dmabuf_mgr;
++	void *rc;
++
++	rc = optee_ffa_shm_pool_alloc_pages();
++	if (IS_ERR(rc))
++		return rc;
++	priv_mgr = rc;
++
++	rc = optee_ffa_shm_pool_alloc_pages();
++	if (IS_ERR(rc)) {
++		tee_shm_pool_mgr_destroy(priv_mgr);
++		return rc;
++	}
++	dmabuf_mgr = rc;
++
++	rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
++	if (IS_ERR(rc)) {
++		tee_shm_pool_mgr_destroy(priv_mgr);
++		tee_shm_pool_mgr_destroy(dmabuf_mgr);
++	}
++
++	return rc;
++}
++
++static const struct tee_driver_ops optee_ffa_clnt_ops = {
++	.get_version = optee_ffa_get_version,
++	.open = optee_open,
++	.release = optee_release,
++	.open_session = optee_open_session,
++	.close_session = optee_close_session,
++	.invoke_func = optee_invoke_func,
++	.cancel_req = optee_cancel_req,
++	.shm_register = optee_ffa_shm_register,
++	.shm_unregister = optee_ffa_shm_unregister,
++};
++
++static const struct tee_desc optee_ffa_clnt_desc = {
++	.name = DRIVER_NAME "ffa-clnt",
++	.ops = &optee_ffa_clnt_ops,
++	.owner = THIS_MODULE,
++};
++
++static const struct tee_driver_ops optee_ffa_supp_ops = {
++	.get_version = optee_ffa_get_version,
++	.open = optee_open,
++	.release = optee_release_supp,
++	.supp_recv = optee_supp_recv,
++	.supp_send = optee_supp_send,
++	.shm_register = optee_ffa_shm_register, /* same as for clnt ops */
++	.shm_unregister = optee_ffa_shm_unregister_supp,
++};
++
++static const struct tee_desc optee_ffa_supp_desc = {
++	.name = DRIVER_NAME "ffa-supp",
++	.ops = &optee_ffa_supp_ops,
++	.owner = THIS_MODULE,
++	.flags = TEE_DESC_PRIVILEGED,
++};
++
++static const struct optee_ops optee_ffa_ops = {
++	.do_call_with_arg = optee_ffa_do_call_with_arg,
++	.to_msg_param = optee_ffa_to_msg_param,
++	.from_msg_param = optee_ffa_from_msg_param,
++};
++
++static struct optee *optee_probe_ffa(void)
++{
++	struct tee_device *teedev = NULL;
++	struct ffa_ops *ffa_ops = NULL;
++	struct optee *optee = NULL;
++	struct ffa_partition_info *partition_info = NULL;
++	u32 ffa_dst = 0;
++	u32 sec_caps = 0;
++	int count = 0;
++	int rc = 0;
++
++	ffa_ops = get_ffa_ops();
++	if (!ffa_ops) {
++		pr_warn("failed \"method\" init: ffa\n");
++		return ERR_PTR(-ENOENT);
++	}
++	/* Use OPTEE UUID to retrieve partition ID. */
++        count = ffa_ops->partition_info_get(OPTEE_MSG_OS_OPTEE_UUID_0,
++					     OPTEE_MSG_OS_OPTEE_UUID_1,
++					     OPTEE_MSG_OS_OPTEE_UUID_2,
++					     OPTEE_MSG_OS_OPTEE_UUID_3,
++					     &partition_info);
++
++	/* If count is negative propergate the error code. */
++	if (count < 0) {
++		return ERR_PTR(count);
++	}
++	/*
++	 * If the function returned sucessfully we must ensure to free the
++	 * allocated memory before exiting.
++	 */
++
++	/* Check only a single patition is found.*/
++	/* TODO: Add support for dealing with multiple partitions. */
++	if (count > SUPPORTED_OPTEE_PARTITIONS) {
++		kfree(partition_info);
++		return ERR_PTR(-EINVAL);
++	}
++	ffa_dst = partition_info[0].id;
++	kfree(partition_info);
++
++	if (!optee_ffa_api_is_compatbile(ffa_ops, ffa_dst))
++		return ERR_PTR(-EINVAL);
++
++	if (!optee_ffa_exchange_caps(ffa_ops, ffa_dst, &sec_caps))
++		return ERR_PTR(-EINVAL);
++
++	optee = kzalloc(sizeof(*optee), GFP_KERNEL);
++	if (!optee) {
++		rc = -ENOMEM;
++		goto err;
++	}
++	optee->pool = optee_ffa_config_dyn_shm();
++	if (IS_ERR(optee->pool)) {
++		rc = PTR_ERR(optee->pool);
++		optee->pool = NULL;
++		goto err;
++	}
++
++	optee->ops = &optee_ffa_ops;
++	optee->ffa.ops = ffa_ops;
++	optee->ffa.dst = ffa_dst;
++	optee->sec_caps = sec_caps;
++
++	teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
++				  optee);
++	if (IS_ERR(teedev)) {
++		rc = PTR_ERR(teedev);
++		goto err;
++	}
++	optee->teedev = teedev;
++
++	teedev = tee_device_alloc(&optee_ffa_supp_desc, NULL, optee->pool,
++				  optee);
++	if (IS_ERR(teedev)) {
++		rc = PTR_ERR(teedev);
++		goto err;
++	}
++	optee->supp_teedev = teedev;
++
++	rc = tee_device_register(optee->teedev);
++	if (rc)
++		goto err;
++
++	rc = tee_device_register(optee->supp_teedev);
++	if (rc)
++		goto err;
++
++	rc = rhashtable_init(&optee->ffa.global_ids, &shm_rhash_params);
++	if (rc)
++		goto err;
++	mutex_init(&optee->ffa.mutex);
++	mutex_init(&optee->call_queue.mutex);
++	INIT_LIST_HEAD(&optee->call_queue.waiters);
++	optee_wait_queue_init(&optee->wait_queue);
++	optee_supp_init(&optee->supp);
++
++	return optee;
++err:
++	/*
++	 * tee_device_unregister() is safe to call even if the
++	 * devices hasn't been registered with
++	 * tee_device_register() yet.
++	 */
++	tee_device_unregister(optee->supp_teedev);
++	tee_device_unregister(optee->teedev);
++	if (optee->pool)
++		tee_shm_pool_free(optee->pool);
++	kfree(optee);
++	return ERR_PTR(rc);
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
++static const char *get_conduit_method(struct device_node *np)
++{
++	const char *method = NULL;
++
++	pr_info("probing for conduit method from DT.\n");
++
++	if (of_property_read_string(np, "method", &method)) {
++		pr_warn("missing \"method\" property\n");
++		return NULL;
++	}
++
++	return method;
++}
++
++static struct optee *optee_probe(struct device_node *np)
++{
++	const char *method = get_conduit_method(np);
++
++	if (!method)
++		return ERR_PTR(-ENXIO);
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++	if (!strcmp(method, "ffa"))
++		return optee_probe_ffa();
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
++
++	return optee_probe_legacy(method);
++}
++
+ static void optee_remove(struct optee *optee)
+ {
+ 	/*
+@@ -669,7 +1170,10 @@ static void optee_remove(struct optee *optee)
+ 	 * reference counters and also avoid wild pointers in secure world
+ 	 * into the old shared memory range.
+ 	 */
+-	optee_disable_shm_cache(optee);
++	if (optee->invoke_fn)
++		optee_disable_shm_cache(optee);
++	else
++		optee_ffa_disable_shm_cache(optee);
+ 
+ 	/*
+ 	 * The two devices has to be unregistered before we can free the
+@@ -684,6 +1188,13 @@ static void optee_remove(struct optee *optee)
+ 	optee_wait_queue_exit(&optee->wait_queue);
+ 	optee_supp_uninit(&optee->supp);
+ 	mutex_destroy(&optee->call_queue.mutex);
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++	if (optee->ffa.ops) {
++		mutex_destroy(&optee->ffa.mutex);
++		rhashtable_free_and_destroy(&optee->ffa.global_ids,
++					    rh_free_fn, NULL);
++	}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+ 
+ 	kfree(optee);
+ }
+diff --git a/drivers/tee/optee/optee_ffa.h b/drivers/tee/optee/optee_ffa.h
+new file mode 100644
+index 000000000000..768e056ab491
+--- /dev/null
++++ b/drivers/tee/optee/optee_ffa.h
+@@ -0,0 +1,201 @@
++/* SPDX-License-Identifier: BSD-2-Clause */
++/*
++ * Copyright (c) 2019, Linaro Limited
++ */
++
++/*
++ * This file is exported by OP-TEE and is in kept in sync between secure
++ * world and normal world kernel driver. We're using ARM FF-A 1.0 EAC
++ * specification.
++ */
++
++#ifndef __OPTEE_FFA_H
++#define __OPTEE_FFA_H
++
++#include <linux/arm_ffa.h>
++
++/*
++ * Normal world sends requests with FFA_MSG_SEND_DIRECT_REQ and
++ * responses are returned with FFA_MSG_SEND_DIRECT_RESP for normal
++ * messages.
++ *
++ * All requests with FFA_MSG_SEND_DIRECT_REQ and FFA_MSG_SEND_DIRECT_RESP
++ * are using the AArch32 SMC calling convention with register usage as
++ * defined in FF-A specification:
++ * w0:    Function ID (0x8400006F or 0x84000070)
++ * w1:    Source/Destination IDs
++ * w2:    Reserved (MBZ)
++ * w3-w7: Implementation defined, free to be used below
++ */
++
++#define OPTEE_FFA_VERSION_MAJOR	1
++#define OPTEE_FFA_VERSION_MINOR	0
++
++#define OPTEE_FFA_BLOCKING_CALL(id)	(id)
++#define OPTEE_FFA_YIELDING_CALL_BIT	31
++#define OPTEE_FFA_YIELDING_CALL(id)	((id) | BIT(OPTEE_FFA_YIELDING_CALL_BIT))
++
++/*
++ * Returns the API version implemented, currently follows the FF-A version.
++ * Call register usage:
++ * w3:    Service ID, OPTEE_FFA_GET_API_VERSION
++ * w4-w7: Not used (MBZ)
++ *
++ * Return register usage:
++ * w3:    OPTEE_FFA_VERSION_MAJOR
++ * w4:    OPTEE_FFA_VERSION_MINOR
++ * w5-w7: Not used (MBZ)
++ */
++#define OPTEE_FFA_GET_API_VERSION	OPTEE_FFA_BLOCKING_CALL(0)
++
++/*
++ * Returns the revision of OP-TEE.
++ *
++ * Used by non-secure world to figure out which version of the Trusted OS
++ * is installed. Note that the returned revision is the revision of the
++ * Trusted OS, not of the API.
++ *
++ * Call register usage:
++ * w3:    Service ID, OPTEE_FFA_GET_OS_VERSION
++ * w4-w7: Unused (MBZ)
++ *
++ * Return register usage:
++ * w3:    CFG_OPTEE_REVISION_MAJOR
++ * w4:    CFG_OPTEE_REVISION_MINOR
++ * w5:    TEE_IMPL_GIT_SHA1 (or zero if not supported)
++ */
++#define OPTEE_FFA_GET_OS_VERSION	OPTEE_FFA_BLOCKING_CALL(1)
++
++/*
++ * Exchange capabilities between normal world and secure world.
++ *
++ * Currently there are no defined capabilities. When features are added new
++ * capabilities may be added.
++ *
++ * Call register usage:
++ * w3:    Service ID, OPTEE_FFA_EXCHANGE_CAPABILITIES
++ * w4-w7: Note used (MBZ)
++ *
++ * Return register usage:
++ * w3:    Error code, 0 on success
++ * w4:    Bit[1:0]:  Number of pages of shared memory to register with
++ *                   OPTEE_FFA_REGISTER_RPC_SHM to support RPC
++ *        Bit[31:2]: Reserved (MBZ)
++ * w5-w7: Note used (MBZ)
++ */
++#define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
++
++/*
++ * Call with struct optee_msg_arg as argument in the supplied shared memory
++ * with a zero internal offset and normal cached memory attributes.
++ * Register usage:
++ * w3:    Service ID, OPTEE_FFA_YIELDING_CALL_WITH_ARG
++ * w4:    Shared memory handle, lower bits
++ * w5:    Shared memory handle, higher bits
++ * w6:    Offset into shared memory pointing to a struct optee_msg_arg
++ * w7:    Not used (MBZ)
++ *
++ * Call to register shared memory memory. The data is supplied in shared
++ * memory with a zero internal offset and normal cached memory attributes.
++ * The data is formatted as described in FFA 1.0 Beta1 Table 137 "
++ * Descriptor to retrieve a donated, lent or shared memory region".
++ * Register usage:
++ * w3:    Service ID, OPTEE_FFA_YIELDING_CALL_REGISTER_SHM
++ * w4:    Shared memory handle, lower bits
++ * w5:    Shared memory handle, higher bits
++ * w6-w7: Not used (MBZ)
++ *
++ * Call unregister shared memory register usage:
++ * w3:    Service ID, OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
++ * w4:    Shared memory handle, lower bits
++ * w5:    Shared memory handle, higher bits
++ * w6-w7: Not used (MBZ)
++ *
++ * Resume from RPC register usage:
++ * w3:    Service ID, OPTEE_FFA_YIELDING_CALL_RESUME
++ * If returning from OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SHM:
++ *	w4:    Shared memory handle, lower bits
++ *	w5:    Shared memory handle, higher bits
++ *	       If the allocation failed both w4 and w5 are 0
++ *	w6:    Offset into shared memory pointing the table If internal
++ *	       offset > 0 then one more page than requested has been allocated.
++ * else if resuming from another RPC:
++ *	w4-w6: Not used (MBZ)
++ * w7:    Resume info
++ *
++ * Normal return (yielding call is completed) register usage:
++ * w3:    Error code, 0 on success
++ * w4:    OPTEE_FFA_YIELDING_CALL_RETURN_DONE
++ * w5-w7: Not used (MBZ)
++ *
++ * Alloc SHM return (RPC from secure world) register usage:
++ * w3:    Error code == 0
++ * w4:    OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
++ *	  OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM
++ *	  allocate kernel private or supplicant memory respectively.
++ * w5:    Number of pages of shared memory
++ * w6:    Not used (MBZ)
++ * w7:    Resume info
++ *
++ * Free SHM return (RPC from secure world) register usage:
++ * w3:    Error code == 0
++ * w4:    OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM or
++ *	  OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM
++ *	  free kernel private or supplicant memory respectively.
++ * w5	  Shared memory handle to free, lower bits
++ * w6	  Shared memory handle to free, higher bits
++ *	  The handle previously allocated with
++ *	  OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM or
++ *	  OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM.
++ * w7:    Resume info
++ *
++ * RPC cmd return (RPC from secure world) register usage:
++ * w3:    Error code == 0
++ * w4:    OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD
++ * w5:    Shared memory handle, lower bits
++ * w6:    Shared memory handle, higher bits
++ *	  The handle contains aed the RPC.
++ * w7:    Resume info
++ *
++ * RPC interrupt return (RPC from secure world) register usage:
++ * w3:    Error code == 0
++ * w4:    OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT
++ * w5-w6: Not used (MBZ)
++ * w7:    Resume info
++ *
++ * Possible error codes in register w3:
++ * 0:                       Success
++ * FFA_DENIED:             w4 isn't one of OPTEE_FFA_YIELDING_CALL_START
++ *                          OPTEE_FFA_YIELDING_CALL_REGISTER_SHM,
++ *                          OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM or
++ *                          OPTEE_FFA_YIELDING_CALL_RESUME
++ *
++ * Possible error codes for OPTEE_FFA_YIELDING_CALL_START,
++ * OPTEE_FFA_YIELDING_CALL_REGISTER_SHM and
++ * OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM
++ * FFA_BUSY:               Number of OP-TEE OS threads exceeded,
++ *                          try again later
++ * FFA_DENIED:             RPC shared memory object not found
++ * FFA_INVALID_PARAMETER:  Bad shared memory handle or offset into the memory
++ *
++ * Possible error codes for OPTEE_FFA_YIELDING_CALL_RESUME
++ * FFA_INVALID_PARAMETER:  Bad resume info
++ *
++ */
++#define OPTEE_FFA_YIELDING_CALL_WITH_ARG	OPTEE_FFA_YIELDING_CALL(0)
++#define OPTEE_FFA_YIELDING_CALL_REGISTER_SHM	OPTEE_FFA_YIELDING_CALL(1)
++#define OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM	OPTEE_FFA_YIELDING_CALL(2)
++#define OPTEE_FFA_YIELDING_CALL_RESUME		OPTEE_FFA_YIELDING_CALL(3)
++
++#define OPTEE_FFA_YIELDING_CALL_RETURN_DONE		0
++#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM	1
++#define OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM	2
++#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED0	3
++#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM	4
++#define OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM	5
++#define OPTEE_FFA_YIELDING_CALL_RETURN_RESERVED1	6
++#define OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD		7
++#define OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT	8
++
++#endif /*__OPTEE_FFA_H*/
++
+diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
+index 795bc19ae17a..95ee82c11733 100644
+--- a/drivers/tee/optee/optee_msg.h
++++ b/drivers/tee/optee/optee_msg.h
+@@ -1,6 +1,5 @@
+-/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+ /*
+- * Copyright (c) 2015-2019, Linaro Limited
++ * Copyright (c) 2015-2020, Linaro Limited
+  */
+ #ifndef _OPTEE_MSG_H
+ #define _OPTEE_MSG_H
+@@ -11,12 +10,6 @@
+ /*
+  * This file defines the OP-TEE message protocol used to communicate
+  * with an instance of OP-TEE running in secure world.
+- *
+- * This file is divided into three sections.
+- * 1. Formatting of messages.
+- * 2. Requests from normal world
+- * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
+- *    tee-supplicant.
+  */
+ 
+ /*****************************************************************************
+@@ -30,6 +23,9 @@
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT		0x5
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT		0x6
+ #define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT		0x7
++#define OPTEE_MSG_ATTR_TYPE_SMEM_INPUT		OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
++#define OPTEE_MSG_ATTR_TYPE_SMEM_OUTPUT		OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
++#define OPTEE_MSG_ATTR_TYPE_SMEM_INOUT		OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT		0x9
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT		0xa
+ #define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT		0xb
+@@ -54,14 +50,14 @@
+  * Every entry in buffer should point to a 4k page beginning (12 least
+  * significant bits must be equal to zero).
+  *
+- * 12 least significant bints of optee_msg_param.u.tmem.buf_ptr should hold page
+- * offset of the user buffer.
++ * 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold
++ * page offset of user buffer.
+  *
+  * So, entries should be placed like members of this structure:
+  *
+  * struct page_data {
+- *   uint64_t pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(uint64_t) - 1];
+- *   uint64_t next_page_data;
++ *   u64 pages_array[OPTEE_MSG_NONCONTIG_PAGE_SIZE/sizeof(u64) - 1];
++ *   u64 next_page_data;
+  * };
+  *
+  * Structure is designed to exactly fit into the page size
+@@ -129,6 +125,23 @@ struct optee_msg_param_rmem {
+ 	u64 shm_ref;
+ };
+ 
++/**
++ * struct optee_msg_param_smem - ffa memory reference parameter
++ * @offs_lower:	   Lower bits of offset into shared memory reference
++ * @offs_upper:	   Upper bits of offset into shared memory reference
++ * @internal_offs: Internal offset into the first page of shared memory
++ *		   reference
++ * @size:	   Size of the buffer
++ * @global_id:	   Global identifier of Shared memory
++ */
++struct optee_msg_param_smem {
++	u32 offs_low;
++	u16 offs_high;
++	u16 internal_offs;
++	u64 size;
++	u64 global_id;
++};
++
+ /**
+  * struct optee_msg_param_value - opaque value parameter
+  *
+@@ -145,12 +158,14 @@ struct optee_msg_param_value {
+  * @attr:	attributes
+  * @tmem:	parameter by temporary memory reference
+  * @rmem:	parameter by registered memory reference
++ * @smem:	parameter by ffa registered memory reference
+  * @value:	parameter by opaque value
+  *
+  * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
+  * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
+  * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
+- * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates @rmem,
++ * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_SMEM_* indicates
++ * @rmem or @smem depending on the conduit.
+  * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
+  */
+ struct optee_msg_param {
+@@ -158,6 +173,7 @@ struct optee_msg_param {
+ 	union {
+ 		struct optee_msg_param_tmem tmem;
+ 		struct optee_msg_param_rmem rmem;
++		struct optee_msg_param_smem smem;
+ 		struct optee_msg_param_value value;
+ 	} u;
+ };
+@@ -176,17 +192,9 @@ struct optee_msg_param {
+  * @params: the parameters supplied to the OS Command
+  *
+  * All normal calls to Trusted OS uses this struct. If cmd requires further
+- * information than what these field holds it can be passed as a parameter
++ * information than what these fields hold it can be passed as a parameter
+  * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
+- * attrs field). All parameters tagged as meta has to come first.
+- *
+- * Temp memref parameters can be fragmented if supported by the Trusted OS
+- * (when optee_smc.h is bearer of this protocol this is indicated with
+- * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
+- * fragmented then has all but the last fragment the
+- * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
+- * it will still be presented as a single logical memref to the Trusted
+- * Application.
++ * attrs field). All parameters tagged as meta have to come first.
+  */
+ struct optee_msg_arg {
+ 	u32 cmd;
+@@ -199,7 +207,7 @@ struct optee_msg_arg {
+ 	u32 num_params;
+ 
+ 	/* num_params tells the actual number of element in params */
+-	struct optee_msg_param params[0];
++	struct optee_msg_param params[];
+ };
+ 
+ /**
+@@ -290,13 +298,10 @@ struct optee_msg_arg {
+  * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
+  * information is passed as:
+  * [in] param[0].attr			OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+- *					[| OPTEE_MSG_ATTR_FRAGMENT]
++ *					[| OPTEE_MSG_ATTR_NONCONTIG]
+  * [in] param[0].u.tmem.buf_ptr		physical address (of first fragment)
+  * [in] param[0].u.tmem.size		size (of first fragment)
+  * [in] param[0].u.tmem.shm_ref		holds shared memory reference
+- * ...
+- * The shared memory can optionally be fragmented, temp memrefs can follow
+- * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
+  *
+  * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
+  * memory reference. The information is passed as:
+@@ -313,110 +318,4 @@ struct optee_msg_arg {
+ #define OPTEE_MSG_CMD_UNREGISTER_SHM	5
+ #define OPTEE_MSG_FUNCID_CALL_WITH_ARG	0x0004
+ 
+-/*****************************************************************************
+- * Part 3 - Requests from secure world, RPC
+- *****************************************************************************/
+-
+-/*
+- * All RPC is done with a struct optee_msg_arg as bearer of information,
+- * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
+- *
+- * RPC communication with tee-supplicant is reversed compared to normal
+- * client communication desribed above. The supplicant receives requests
+- * and sends responses.
+- */
+-
+-/*
+- * Load a TA into memory, defined in tee-supplicant
+- */
+-#define OPTEE_MSG_RPC_CMD_LOAD_TA	0
+-
+-/*
+- * Reserved
+- */
+-#define OPTEE_MSG_RPC_CMD_RPMB		1
+-
+-/*
+- * File system access, defined in tee-supplicant
+- */
+-#define OPTEE_MSG_RPC_CMD_FS		2
+-
+-/*
+- * Get time
+- *
+- * Returns number of seconds and nano seconds since the Epoch,
+- * 1970-01-01 00:00:00 +0000 (UTC).
+- *
+- * [out] param[0].u.value.a	Number of seconds
+- * [out] param[0].u.value.b	Number of nano seconds.
+- */
+-#define OPTEE_MSG_RPC_CMD_GET_TIME	3
+-
+-/*
+- * Wait queue primitive, helper for secure world to implement a wait queue.
+- *
+- * If secure world need to wait for a secure world mutex it issues a sleep
+- * request instead of spinning in secure world. Conversely is a wakeup
+- * request issued when a secure world mutex with a thread waiting thread is
+- * unlocked.
+- *
+- * Waiting on a key
+- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
+- * [in] param[0].u.value.b wait key
+- *
+- * Waking up a key
+- * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
+- * [in] param[0].u.value.b wakeup key
+- */
+-#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE	4
+-#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP	0
+-#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP	1
+-
+-/*
+- * Suspend execution
+- *
+- * [in] param[0].value	.a number of milliseconds to suspend
+- */
+-#define OPTEE_MSG_RPC_CMD_SUSPEND	5
+-
+-/*
+- * Allocate a piece of shared memory
+- *
+- * Shared memory can optionally be fragmented, to support that additional
+- * spare param entries are allocated to make room for eventual fragments.
+- * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
+- * unused. All returned temp memrefs except the last should have the
+- * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
+- *
+- * [in]  param[0].u.value.a		type of memory one of
+- *					OPTEE_MSG_RPC_SHM_TYPE_* below
+- * [in]  param[0].u.value.b		requested size
+- * [in]  param[0].u.value.c		required alignment
+- *
+- * [out] param[0].u.tmem.buf_ptr	physical address (of first fragment)
+- * [out] param[0].u.tmem.size		size (of first fragment)
+- * [out] param[0].u.tmem.shm_ref	shared memory reference
+- * ...
+- * [out] param[n].u.tmem.buf_ptr	physical address
+- * [out] param[n].u.tmem.size		size
+- * [out] param[n].u.tmem.shm_ref	shared memory reference (same value
+- *					as in param[n-1].u.tmem.shm_ref)
+- */
+-#define OPTEE_MSG_RPC_CMD_SHM_ALLOC	6
+-/* Memory that can be shared with a non-secure user space application */
+-#define OPTEE_MSG_RPC_SHM_TYPE_APPL	0
+-/* Memory only shared with non-secure kernel */
+-#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL	1
+-
+-/*
+- * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
+- *
+- * [in]  param[0].u.value.a		type of memory one of
+- *					OPTEE_MSG_RPC_SHM_TYPE_* above
+- * [in]  param[0].u.value.b		value of shared memory reference
+- *					returned in param[0].u.tmem.shm_ref
+- *					above
+- */
+-#define OPTEE_MSG_RPC_CMD_SHM_FREE	7
+-
+ #endif /* _OPTEE_MSG_H */
+diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
+index d9c5037b4e03..d12d9b9f6d33 100644
+--- a/drivers/tee/optee/optee_private.h
++++ b/drivers/tee/optee/optee_private.h
+@@ -7,6 +7,7 @@
+ #define OPTEE_PRIVATE_H
+ 
+ #include <linux/arm-smccc.h>
++#include <linux/rhashtable.h>
+ #include <linux/semaphore.h>
+ #include <linux/tee_drv.h>
+ #include <linux/types.h>
+@@ -17,6 +18,7 @@
+ /* Some Global Platform error codes used in this driver */
+ #define TEEC_SUCCESS			0x00000000
+ #define TEEC_ERROR_BAD_PARAMETERS	0xFFFF0006
++#define TEEC_ERROR_NOT_SUPPORTED	0xFFFF000A
+ #define TEEC_ERROR_COMMUNICATION	0xFFFF000E
+ #define TEEC_ERROR_OUT_OF_MEMORY	0xFFFF000C
+ #define TEEC_ERROR_SHORT_BUFFER		0xFFFF0010
+@@ -65,6 +67,32 @@ struct optee_supp {
+ 	struct completion reqs_c;
+ };
+ 
++/**
++ * struct optee_ffa_data -  FFA communication struct
++ * @dst			FFA destination id, the id of OP-TEE in secure world
++ * @ops			FFA operations
++ * @mutex		Serializes access to @global_ids
++ * @global_ids		FF-A shared memory global handle translation
++ */
++struct optee_ffa {
++	u32 dst;
++	struct ffa_ops *ops;
++	struct mutex mutex;
++	struct rhashtable global_ids;
++};
++
++struct optee;
++struct optee_ops {
++	int (*do_call_with_arg)(struct tee_context *ctx,
++				struct tee_shm *shm_arg);
++	int (*to_msg_param)(struct optee *optee,
++			    struct optee_msg_param *msg_params,
++			    size_t num_params, const struct tee_param *params);
++	int (*from_msg_param)(struct optee *optee, struct tee_param *params,
++			      size_t num_params,
++			      const struct optee_msg_param *msg_params);
++};
++
+ /**
+  * struct optee - main service struct
+  * @supp_teedev:	supplicant device
+@@ -82,7 +110,11 @@ struct optee_supp {
+ struct optee {
+ 	struct tee_device *supp_teedev;
+ 	struct tee_device *teedev;
++	const struct optee_ops *ops;
+ 	optee_invoke_fn *invoke_fn;
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++	struct optee_ffa ffa;
++#endif
+ 	struct optee_call_queue call_queue;
+ 	struct optee_wait_queue wait_queue;
+ 	struct optee_supp supp;
+@@ -141,10 +173,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+ 		    struct tee_param *param);
+ 
+-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
++int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
+ int optee_open_session(struct tee_context *ctx,
+ 		       struct tee_ioctl_open_session_arg *arg,
+ 		       struct tee_param *param);
++int optee_close_session_helper(struct tee_context *ctx, u32 session);
+ int optee_close_session(struct tee_context *ctx, u32 session);
+ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+ 		      struct tee_param *param);
+@@ -163,11 +196,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
+ 			    unsigned long start);
+ int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
+ 
+-int optee_from_msg_param(struct tee_param *params, size_t num_params,
+-			 const struct optee_msg_param *msg_params);
+-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+-		       const struct tee_param *params);
+-
+ u64 *optee_allocate_pages_list(size_t num_entries);
+ void optee_free_pages_list(void *array, size_t num_entries);
+ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+@@ -175,6 +203,27 @@ void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
+ 
+ int optee_enumerate_devices(void);
+ 
++int optee_shm_add_ffa_handle(struct optee *optee, struct tee_shm *shm,
++			     u64 global_id);
++int optee_shm_rem_ffa_handle(struct optee *optee, u64 global_id);
++
++struct tee_shm *optee_shm_from_ffa_handle(struct optee *optee, u64 global_id);
++void optee_ffa_disable_shm_cache(struct optee *optee);
++
++int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
++			    struct page **pages, size_t num_pages,
++			    unsigned long start);
++int optee_ffa_shm_unregister(struct tee_context *ctx, struct tee_shm *shm);
++int optee_ffa_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
++				 struct page **pages, size_t num_pages,
++				 unsigned long start);
++int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
++				   struct tee_shm *shm);
++
++int optee_ffa_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
++int optee_ffa_rpc_shm_register(struct tee_context *ctx, struct tee_shm *shm);
++void optee_handle_ffa_rpc(struct tee_context *ctx, u32 *w4, u32 *w5, u32 *w6);
++
+ /*
+  * Small helpers
+  */
+diff --git a/drivers/tee/optee/optee_rpc_cmd.h b/drivers/tee/optee/optee_rpc_cmd.h
+new file mode 100644
+index 000000000000..712aa32513d7
+--- /dev/null
++++ b/drivers/tee/optee/optee_rpc_cmd.h
+@@ -0,0 +1,333 @@
++/* SPDX-License-Identifier: BSD-2-Clause */
++/*
++ * Copyright (c) 2016-2018, Linaro Limited
++ */
++
++#ifndef __OPTEE_RPC_CMD_H
++#define __OPTEE_RPC_CMD_H
++
++/*
++ * All RPC is done with a struct optee_msg_arg as bearer of information,
++ * struct optee_msg_arg::arg holds values defined by OPTEE_RPC_CMD_* below.
++ * Only the commands handled by the kernel driver are defined here.
++ *
++ * RPC communication with tee-supplicant is reversed compared to normal
++ * client communication described above. The supplicant receives requests
++ * and sends responses.
++ */
++
++/*
++ * Load a TA into memory
++ *
++ * Since the size of the TA isn't known in advance the size of the TA is
++ * can be queried with a NULL buffer.
++ *
++ * [in]     value[0].a-b    UUID
++ * [out]    memref[1]	    Buffer with TA
++ */
++#define OPTEE_RPC_CMD_LOAD_TA		0
++
++/*
++ * Replay Protected Memory Block access
++ *
++ * [in]     memref[0]	    Frames to device
++ * [out]    memref[1]	    Frames from device
++ */
++#define OPTEE_RPC_CMD_RPMB		1
++
++/*
++ * File system access, see definition of protocol below
++ */
++#define OPTEE_RPC_CMD_FS		2
++
++/*
++ * Get time
++ *
++ * Returns number of seconds and nano seconds since the Epoch,
++ * 1970-01-01 00:00:00 +0000 (UTC).
++ *
++ * [out]    value[0].a	    Number of seconds
++ * [out]    value[0].b	    Number of nano seconds.
++ */
++#define OPTEE_RPC_CMD_GET_TIME		3
++
++/*
++ * Wait queue primitive, helper for secure world to implement a wait queue.
++ *
++ * If secure world needs to wait for a secure world mutex it issues a sleep
++ * request instead of spinning in secure world. Conversely is a wakeup
++ * request issued when a secure world mutex with a thread waiting thread is
++ * unlocked.
++ *
++ * Waiting on a key
++ * [in]    value[0].a	    OPTEE_RPC_WAIT_QUEUE_SLEEP
++ * [in]    value[0].b	    Wait key
++ *
++ * Waking up a key
++ * [in]    value[0].a	    OPTEE_RPC_WAIT_QUEUE_WAKEUP
++ * [in]    value[0].b	    Wakeup key
++ */
++#define OPTEE_RPC_CMD_WAIT_QUEUE	4
++#define OPTEE_RPC_WAIT_QUEUE_SLEEP	0
++#define OPTEE_RPC_WAIT_QUEUE_WAKEUP	1
++
++/*
++ * Suspend execution
++ *
++ * [in]    value[0].a	Number of milliseconds to suspend
++ */
++#define OPTEE_RPC_CMD_SUSPEND		5
++
++/*
++ * Allocate a piece of shared memory
++ *
++ * [in]    value[0].a	    Type of memory one of
++ *			    OPTEE_RPC_SHM_TYPE_* below
++ * [in]    value[0].b	    Requested size
++ * [in]    value[0].c	    Required alignment
++ * [out]   memref[0]	    Buffer
++ */
++#define OPTEE_RPC_CMD_SHM_ALLOC		6
++/* Memory that can be shared with a non-secure user space application */
++#define OPTEE_RPC_SHM_TYPE_APPL		0
++/* Memory only shared with non-secure kernel */
++#define OPTEE_RPC_SHM_TYPE_KERNEL	1
++/*
++ * Memory shared with non-secure kernel and exported to a non-secure user
++ * space application
++ */
++#define OPTEE_RPC_SHM_TYPE_GLOBAL	2
++
++/*
++ * Free shared memory previously allocated with OPTEE_RPC_CMD_SHM_ALLOC
++ *
++ * [in]     value[0].a	    Type of memory one of
++ *			    OPTEE_RPC_SHM_TYPE_* above
++ * [in]     value[0].b	    Value of shared memory reference or cookie
++ */
++#define OPTEE_RPC_CMD_SHM_FREE		7
++
++/* Was OPTEE_RPC_CMD_SQL_FS, which isn't supported any longer */
++#define OPTEE_RPC_CMD_SQL_FS_RESERVED	8
++
++/*
++ * Send TA profiling information to normal world
++ *
++ * [in/out] value[0].a	    File identifier. Must be set to 0 on
++ *			    first call. A value >= 1 will be
++ *			    returned on success. Re-use this value
++ *			    to append data to the same file.
++ * [in]     memref[1]	    TA UUID
++ * [in]     memref[2]	    Profile data
++ */
++#define OPTEE_RPC_CMD_GPROF		9
++
++/*
++ * Socket command, see definition of protocol below
++ */
++#define OPTEE_RPC_CMD_SOCKET		10
++
++/*
++ * Send TA function graph data to normal world
++ *
++ * [in/out] value[0].a	    File identifier. Must be set to 0 on
++ *			    first call. A value >= 1 will be
++ *			    returned on success. Re-use this value
++ *			    to append data to the same file.
++ * [in]     memref[1]	    TA UUID
++ * [in]     memref[2]	    function graph data
++ */
++#define OPTEE_RPC_CMD_FTRACE		11
++
++/*
++ * Register timestamp buffer in the linux kernel optee driver
++ *
++ * [in]     value[0].a	    Subcommand (register buffer, unregister buffer)
++ *			    OPTEE_RPC_CMD_BENCH_REG_* below
++ * [in]     value[0].b	    Physical address of timestamp buffer
++ * [in]     value[0].c	    Size of buffer
++ */
++#define OPTEE_RPC_CMD_BENCH_REG_NEW	0
++#define OPTEE_RPC_CMD_BENCH_REG_DEL	1
++#define OPTEE_RPC_CMD_BENCH_REG		20
++
++/*
++ * Definition of protocol for command OPTEE_RPC_CMD_FS
++ */
++
++/*
++ * Open a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_OPEN
++ * [in]     memref[1]	    A string holding the file name
++ * [out]    value[2].a	    File descriptor of open file
++ */
++#define OPTEE_RPC_FS_OPEN		0
++
++/*
++ * Create a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_CREATE
++ * [in]     memref[1]	    A string holding the file name
++ * [out]    value[2].a	    File descriptor of open file
++ */
++#define OPTEE_RPC_FS_CREATE		1
++
++/*
++ * Close a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_CLOSE
++ * [in]     value[0].b	    File descriptor of open file.
++ */
++#define OPTEE_RPC_FS_CLOSE		2
++
++/*
++ * Read from a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_READ
++ * [in]     value[0].b	    File descriptor of open file
++ * [in]     value[0].c	    Offset into file
++ * [out]    memref[1]	    Buffer to hold returned data
++ */
++#define OPTEE_RPC_FS_READ		3
++
++/*
++ * Write to a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_WRITE
++ * [in]     value[0].b	    File descriptor of open file
++ * [in]     value[0].c	    Offset into file
++ * [in]     memref[1]	    Buffer holding data to be written
++ */
++#define OPTEE_RPC_FS_WRITE		4
++
++/*
++ * Truncate a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_TRUNCATE
++ * [in]     value[0].b	    File descriptor of open file
++ * [in]     value[0].c	    Length of file.
++ */
++#define OPTEE_RPC_FS_TRUNCATE		5
++
++/*
++ * Remove a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_REMOVE
++ * [in]     memref[1]	    A string holding the file name
++ */
++#define OPTEE_RPC_FS_REMOVE		6
++
++/*
++ * Rename a file
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_RENAME
++ * [in]     value[0].b	    True if existing target should be removed
++ * [in]     memref[1]	    A string holding the old file name
++ * [in]     memref[2]	    A string holding the new file name
++ */
++#define OPTEE_RPC_FS_RENAME		7
++
++/*
++ * Opens a directory for file listing
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_OPENDIR
++ * [in]     memref[1]	    A string holding the name of the directory
++ * [out]    value[2].a	    Handle to open directory
++ */
++#define OPTEE_RPC_FS_OPENDIR		8
++
++/*
++ * Closes a directory handle
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_CLOSEDIR
++ * [in]     value[0].b	    Handle to open directory
++ */
++#define OPTEE_RPC_FS_CLOSEDIR		9
++
++/*
++ * Read next file name of directory
++ *
++ *
++ * [in]     value[0].a	    OPTEE_RPC_FS_READDIR
++ * [in]     value[0].b	    Handle to open directory
++ * [out]    memref[1]	    A string holding the file name
++ */
++#define OPTEE_RPC_FS_READDIR		10
++
++/* End of definition of protocol for command OPTEE_RPC_CMD_FS */
++
++/*
++ * Definition of protocol for command OPTEE_RPC_CMD_SOCKET
++ */
++
++#define OPTEE_RPC_SOCKET_TIMEOUT_NONBLOCKING	0
++#define OPTEE_RPC_SOCKET_TIMEOUT_BLOCKING	0xffffffff
++
++/*
++ * Open socket
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_OPEN
++ * [in]     value[0].b	    TA instance id
++ * [in]     value[1].a	    Server port number
++ * [in]     value[1].b	    Protocol, TEE_ISOCKET_PROTOCOLID_*
++ * [in]     value[1].c	    Ip version TEE_IP_VERSION_* from tee_ipsocket.h
++ * [in]     memref[2]	    Server address
++ * [out]    value[3].a	    Socket handle (32-bit)
++ */
++#define OPTEE_RPC_SOCKET_OPEN	0
++
++/*
++ * Close socket
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_CLOSE
++ * [in]     value[0].b	    TA instance id
++ * [in]     value[0].c	    Socket handle
++ */
++#define OPTEE_RPC_SOCKET_CLOSE	1
++
++/*
++ * Close all sockets
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_CLOSE_ALL
++ * [in]     value[0].b	    TA instance id
++ */
++#define OPTEE_RPC_SOCKET_CLOSE_ALL 2
++
++/*
++ * Send data on socket
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_SEND
++ * [in]     value[0].b	    TA instance id
++ * [in]     value[0].c	    Socket handle
++ * [in]     memref[1]	    Buffer to transmit
++ * [in]     value[2].a	    Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_*
++ * [out]    value[2].b	    Number of transmitted bytes
++ */
++#define OPTEE_RPC_SOCKET_SEND	3
++
++/*
++ * Receive data on socket
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_RECV
++ * [in]     value[0].b	    TA instance id
++ * [in]     value[0].c	    Socket handle
++ * [out]    memref[1]	    Buffer to receive
++ * [in]     value[2].a	    Timeout ms or OPTEE_RPC_SOCKET_TIMEOUT_*
++ */
++#define OPTEE_RPC_SOCKET_RECV	4
++
++/*
++ * Perform IOCTL on socket
++ *
++ * [in]     value[0].a	    OPTEE_RPC_SOCKET_IOCTL
++ * [in]     value[0].b	    TA instance id
++ * [in]     value[0].c	    Socket handle
++ * [in/out] memref[1]	    Buffer
++ * [in]     value[2].a	    Ioctl command
++ */
++#define OPTEE_RPC_SOCKET_IOCTL	5
++
++/* End of definition of protocol for command OPTEE_RPC_CMD_SOCKET */
++
++#endif /*__OPTEE_RPC_CMD_H*/
+diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
+index b4ade54d1f28..ca5d5d01b58f 100644
+--- a/drivers/tee/optee/rpc.c
++++ b/drivers/tee/optee/rpc.c
+@@ -9,8 +9,11 @@
+ #include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/tee_drv.h>
++#include "optee_msg.h"
+ #include "optee_private.h"
++#include "optee_rpc_cmd.h"
+ #include "optee_smc.h"
++#include "optee_ffa.h"
+ 
+ struct wq_entry {
+ 	struct list_head link;
+@@ -102,10 +105,10 @@ static void handle_rpc_func_cmd_wq(struct optee *optee,
+ 		goto bad;
+ 
+ 	switch (arg->params[0].u.value.a) {
+-	case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
++	case OPTEE_RPC_WAIT_QUEUE_SLEEP:
+ 		wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
+ 		break;
+-	case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
++	case OPTEE_RPC_WAIT_QUEUE_WAKEUP:
+ 		wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
+ 		break;
+ 	default:
+@@ -140,10 +143,10 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
+ 	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ }
+ 
+-static void handle_rpc_supp_cmd(struct tee_context *ctx,
++static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
+ 				struct optee_msg_arg *arg)
+ {
+-	struct tee_param *params;
++	struct tee_param *params = NULL;
+ 
+ 	arg->ret_origin = TEEC_ORIGIN_COMMS;
+ 
+@@ -154,32 +157,36 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx,
+ 		return;
+ 	}
+ 
+-	if (optee_from_msg_param(params, arg->num_params, arg->params)) {
++	if (optee->ops->from_msg_param(optee, params, arg->num_params,
++				       arg->params)) {
+ 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ 		goto out;
+ 	}
+ 
+ 	arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
+ 
+-	if (optee_to_msg_param(arg->params, arg->num_params, params))
++	if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
++				     params))
+ 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+ out:
+ 	kfree(params);
+ }
+ 
++
++
+ static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
+ {
+-	u32 ret;
+-	struct tee_param param;
+ 	struct optee *optee = tee_get_drvdata(ctx->teedev);
+-	struct tee_shm *shm;
++	struct tee_param param = { };
++	struct tee_shm *shm = NULL;
++	u32 ret = 0;
+ 
+ 	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+-	param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
++	param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
+ 	param.u.value.b = sz;
+ 	param.u.value.c = 0;
+ 
+-	ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, &param);
++	ret = optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_ALLOC, 1, &param);
+ 	if (ret)
+ 		return ERR_PTR(-ENOMEM);
+ 
+@@ -216,10 +223,10 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+ 
+ 	sz = arg->params[0].u.value.b;
+ 	switch (arg->params[0].u.value.a) {
+-	case OPTEE_MSG_RPC_SHM_TYPE_APPL:
++	case OPTEE_RPC_SHM_TYPE_APPL:
+ 		shm = cmd_alloc_suppl(ctx, sz);
+ 		break;
+-	case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
++	case OPTEE_RPC_SHM_TYPE_KERNEL:
+ 		shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+ 		break;
+ 	default:
+@@ -291,7 +298,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+ 	struct tee_param param;
+ 
+ 	param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+-	param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
++	param.u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
+ 	param.u.value.b = tee_shm_get_id(shm);
+ 	param.u.value.c = 0;
+ 
+@@ -308,7 +315,7 @@ static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+ 	 */
+ 	tee_shm_put(shm);
+ 
+-	optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, &param);
++	optee_supp_thrd_req(ctx, OPTEE_RPC_CMD_SHM_FREE, 1, &param);
+ }
+ 
+ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+@@ -326,10 +333,10 @@ static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+ 
+ 	shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
+ 	switch (arg->params[0].u.value.a) {
+-	case OPTEE_MSG_RPC_SHM_TYPE_APPL:
++	case OPTEE_RPC_SHM_TYPE_APPL:
+ 		cmd_free_suppl(ctx, shm);
+ 		break;
+-	case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
++	case OPTEE_RPC_SHM_TYPE_KERNEL:
+ 		tee_shm_free(shm);
+ 		break;
+ 	default:
+@@ -357,7 +364,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+ 				struct tee_shm *shm,
+ 				struct optee_call_ctx *call_ctx)
+ {
+-	struct optee_msg_arg *arg;
++	struct optee_msg_arg *arg = NULL;
+ 
+ 	arg = tee_shm_get_va(shm, 0);
+ 	if (IS_ERR(arg)) {
+@@ -366,24 +373,24 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+ 	}
+ 
+ 	switch (arg->cmd) {
+-	case OPTEE_MSG_RPC_CMD_GET_TIME:
++	case OPTEE_RPC_CMD_GET_TIME:
+ 		handle_rpc_func_cmd_get_time(arg);
+ 		break;
+-	case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
++	case OPTEE_RPC_CMD_WAIT_QUEUE:
+ 		handle_rpc_func_cmd_wq(optee, arg);
+ 		break;
+-	case OPTEE_MSG_RPC_CMD_SUSPEND:
++	case OPTEE_RPC_CMD_SUSPEND:
+ 		handle_rpc_func_cmd_wait(arg);
+ 		break;
+-	case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
++	case OPTEE_RPC_CMD_SHM_ALLOC:
+ 		free_pages_list(call_ctx);
+ 		handle_rpc_func_cmd_shm_alloc(ctx, arg, call_ctx);
+ 		break;
+-	case OPTEE_MSG_RPC_CMD_SHM_FREE:
++	case OPTEE_RPC_CMD_SHM_FREE:
+ 		handle_rpc_func_cmd_shm_free(ctx, arg);
+ 		break;
+ 	default:
+-		handle_rpc_supp_cmd(ctx, arg);
++		handle_rpc_supp_cmd(ctx, optee, arg);
+ 	}
+ }
+ 
+@@ -441,3 +448,95 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
+ 
+ 	param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static void handle_ffa_rpc_func_cmd(struct tee_context *ctx,
++				     struct optee *optee,
++				     struct optee_msg_arg *arg)
++{
++	switch (arg->cmd) {
++	case OPTEE_RPC_CMD_GET_TIME:
++		handle_rpc_func_cmd_get_time(arg);
++		break;
++	case OPTEE_RPC_CMD_WAIT_QUEUE:
++		handle_rpc_func_cmd_wq(optee, arg);
++		break;
++	case OPTEE_RPC_CMD_SUSPEND:
++		handle_rpc_func_cmd_wait(arg);
++		break;
++	case OPTEE_RPC_CMD_SHM_ALLOC:
++	case OPTEE_RPC_CMD_SHM_FREE:
++		pr_err("%s: RPC cmd 0x%x: not supported\n", __func__,
++		       arg->cmd);
++		arg->ret = TEEC_ERROR_NOT_SUPPORTED;
++		break;
++	default:
++		handle_rpc_supp_cmd(ctx, optee, arg);
++	}
++}
++
++void optee_handle_ffa_rpc(struct tee_context *ctx, u32 *w4, u32 *w5, u32 *w6)
++{
++	struct optee *optee = tee_get_drvdata(ctx->teedev);
++	struct tee_shm *shm = NULL;
++	struct optee_msg_arg *rpc_arg = NULL;
++	u64 global_handle = 0;
++	u32 cmd = *w4;
++
++	switch (cmd) {
++	case OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM:
++	case OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_SUPPL_SHM:
++		if (cmd == OPTEE_FFA_YIELDING_CALL_RETURN_ALLOC_KERN_SHM)
++			shm = tee_shm_alloc(ctx, *w5 * PAGE_SIZE,
++					    TEE_SHM_MAPPED);
++		else
++			shm = cmd_alloc_suppl(ctx, *w5 * PAGE_SIZE);
++
++		if (IS_ERR_OR_NULL(shm))
++			break;
++
++		*w4 = shm->sec_world_id;
++		*w5 = shm->sec_world_id >> 32;
++		*w6 = shm->offset;
++		return;
++	case OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM:
++	case OPTEE_FFA_YIELDING_CALL_RETURN_FREE_SUPPL_SHM:
++		global_handle = *w5 | ((u64)*w6 << 32);
++		shm = optee_shm_from_ffa_handle(optee, global_handle);
++		if (!shm) {
++			pr_err("Invalid global handle 0x%llx\n", global_handle);
++			break;
++		}
++		if (cmd == OPTEE_FFA_YIELDING_CALL_RETURN_FREE_KERN_SHM)
++			tee_shm_free(shm);
++		else
++			cmd_free_suppl(ctx, shm);
++		break;
++	case OPTEE_FFA_YIELDING_CALL_RETURN_RPC_CMD:
++		global_handle = *w5 | ((u64)*w6 << 32);
++		shm = optee_shm_from_ffa_handle(optee, global_handle);
++		if (!shm) {
++			pr_err("Invalid global handle 0x%llx\n", global_handle);
++			break;
++		}
++		rpc_arg = tee_shm_get_va(shm, 0);
++		if (IS_ERR(rpc_arg)) {
++			pr_err("Invalid offset 0 for global handle 0x%llx\n",
++			       global_handle);
++			break;
++		}
++		handle_ffa_rpc_func_cmd(ctx, optee, rpc_arg);
++		break;
++	case OPTEE_FFA_YIELDING_CALL_RETURN_INTERRUPT:
++		/* Interrupt delivered by now */
++		break;
++	default:
++		pr_warn("Unknown RPC func 0x%x\n", cmd);
++		break;
++	}
++
++	*w4 = 0;
++	*w5 = 0;
++	*w6 = 0;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+diff --git a/drivers/tee/optee/shm_pool.c b/drivers/tee/optee/shm_pool.c
+index d767eebf30bd..ffc6821f6ce3 100644
+--- a/drivers/tee/optee/shm_pool.c
++++ b/drivers/tee/optee/shm_pool.c
+@@ -87,3 +87,53 @@ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
+ 
+ 	return mgr;
+ }
++
++#ifdef CONFIG_ARM_FFA_TRANSPORT
++static int pool_ffa_op_alloc(struct tee_shm_pool_mgr *poolm,
++			 struct tee_shm *shm, size_t size)
++{
++	unsigned int order = get_order(size);
++	struct page *page;
++	int rc = 0;
++
++	page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
++	if (!page)
++		return -ENOMEM;
++
++	shm->kaddr = page_address(page);
++	shm->paddr = page_to_phys(page);
++	shm->size = PAGE_SIZE << order;
++
++	shm->flags |= TEE_SHM_REGISTER;
++	rc = optee_ffa_shm_register(shm->ctx, shm, &page, 1 << order,
++				     (unsigned long)shm->kaddr);
++
++	return rc;
++}
++
++static void pool_ffa_op_free(struct tee_shm_pool_mgr *poolm,
++			 struct tee_shm *shm)
++{
++	optee_ffa_shm_unregister(shm->ctx, shm);
++	free_pages((unsigned long)shm->kaddr, get_order(shm->size));
++	shm->kaddr = NULL;
++}
++
++static const struct tee_shm_pool_mgr_ops pool_ffa_ops = {
++	.alloc = pool_ffa_op_alloc,
++	.free = pool_ffa_op_free,
++	.destroy_poolmgr = pool_op_destroy_poolmgr,
++};
++
++struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void)
++{
++	struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
++
++	if (!mgr)
++		return ERR_PTR(-ENOMEM);
++
++	mgr->ops = &pool_ffa_ops;
++
++	return mgr;
++}
++#endif /*CONFIG_ARM_FFA_TRANSPORT*/
+diff --git a/drivers/tee/optee/shm_pool.h b/drivers/tee/optee/shm_pool.h
+index 28109d991c4b..34c5fd74a3ff 100644
+--- a/drivers/tee/optee/shm_pool.h
++++ b/drivers/tee/optee/shm_pool.h
+@@ -10,5 +10,6 @@
+ #include <linux/tee_drv.h>
+ 
+ struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void);
++struct tee_shm_pool_mgr *optee_ffa_shm_pool_alloc_pages(void);
+ 
+ #endif
+diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
+index 3d32a2ca48c3..974fe7081225 100644
+--- a/drivers/tee/tee_core.c
++++ b/drivers/tee/tee_core.c
+@@ -59,7 +59,6 @@ static struct tee_context *teedev_open(struct tee_device *teedev)
+ 
+ 	kref_init(&ctx->refcount);
+ 	ctx->teedev = teedev;
+-	INIT_LIST_HEAD(&ctx->list_shm);
+ 	rc = teedev->desc->ops->open(ctx);
+ 	if (rc)
+ 		goto err;
+diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
+index 09ddcd06c715..deb22f877881 100644
+--- a/drivers/tee/tee_shm.c
++++ b/drivers/tee/tee_shm.c
+@@ -13,13 +13,13 @@
+ 
+ static void tee_shm_release(struct tee_shm *shm)
+ {
+-	struct tee_device *teedev = shm->teedev;
++	struct tee_device *teedev = shm->ctx->teedev;
+ 
+-	mutex_lock(&teedev->mutex);
+-	idr_remove(&teedev->idr, shm->id);
+-	if (shm->ctx)
+-		list_del(&shm->link);
+-	mutex_unlock(&teedev->mutex);
++	if (shm->flags & TEE_SHM_DMA_BUF) {
++		mutex_lock(&teedev->mutex);
++		idr_remove(&teedev->idr, shm->id);
++		mutex_unlock(&teedev->mutex);
++	}
+ 
+ 	if (shm->flags & TEE_SHM_POOL) {
+ 		struct tee_shm_pool_mgr *poolm;
+@@ -44,8 +44,7 @@ static void tee_shm_release(struct tee_shm *shm)
+ 		kfree(shm->pages);
+ 	}
+ 
+-	if (shm->ctx)
+-		teedev_ctx_put(shm->ctx);
++	teedev_ctx_put(shm->ctx);
+ 
+ 	kfree(shm);
+ 
+@@ -82,7 +81,7 @@ static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+ 	size_t size = vma->vm_end - vma->vm_start;
+ 
+ 	/* Refuse sharing shared memory provided by application */
+-	if (shm->flags & TEE_SHM_REGISTER)
++	if (shm->flags & TEE_SHM_USER_MAPPED)
+ 		return -EINVAL;
+ 
+ 	return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
+@@ -97,20 +96,14 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = {
+ 	.mmap = tee_shm_op_mmap,
+ };
+ 
+-static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+-				       struct tee_device *teedev,
+-				       size_t size, u32 flags)
++struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+ {
++	struct tee_device *teedev = ctx->teedev;
+ 	struct tee_shm_pool_mgr *poolm = NULL;
+ 	struct tee_shm *shm;
+ 	void *ret;
+ 	int rc;
+ 
+-	if (ctx && ctx->teedev != teedev) {
+-		dev_err(teedev->dev.parent, "ctx and teedev mismatch\n");
+-		return ERR_PTR(-EINVAL);
+-	}
+-
+ 	if (!(flags & TEE_SHM_MAPPED)) {
+ 		dev_err(teedev->dev.parent,
+ 			"only mapped allocations supported\n");
+@@ -138,7 +131,6 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+ 	}
+ 
+ 	shm->flags = flags | TEE_SHM_POOL;
+-	shm->teedev = teedev;
+ 	shm->ctx = ctx;
+ 	if (flags & TEE_SHM_DMA_BUF)
+ 		poolm = teedev->pool->dma_buf_mgr;
+@@ -151,17 +143,18 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+ 		goto err_kfree;
+ 	}
+ 
+-	mutex_lock(&teedev->mutex);
+-	shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
+-	mutex_unlock(&teedev->mutex);
+-	if (shm->id < 0) {
+-		ret = ERR_PTR(shm->id);
+-		goto err_pool_free;
+-	}
+ 
+ 	if (flags & TEE_SHM_DMA_BUF) {
+ 		DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+ 
++		mutex_lock(&teedev->mutex);
++		shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
++		mutex_unlock(&teedev->mutex);
++		if (shm->id < 0) {
++			ret = ERR_PTR(shm->id);
++			goto err_pool_free;
++		}
++
+ 		exp_info.ops = &tee_shm_dma_buf_ops;
+ 		exp_info.size = shm->size;
+ 		exp_info.flags = O_RDWR;
+@@ -174,18 +167,16 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+ 		}
+ 	}
+ 
+-	if (ctx) {
++	if (ctx)
+ 		teedev_ctx_get(ctx);
+-		mutex_lock(&teedev->mutex);
+-		list_add_tail(&shm->link, &ctx->list_shm);
+-		mutex_unlock(&teedev->mutex);
+-	}
+ 
+ 	return shm;
+ err_rem:
+-	mutex_lock(&teedev->mutex);
+-	idr_remove(&teedev->idr, shm->id);
+-	mutex_unlock(&teedev->mutex);
++	if (flags & TEE_SHM_DMA_BUF) {
++		mutex_lock(&teedev->mutex);
++		idr_remove(&teedev->idr, shm->id);
++		mutex_unlock(&teedev->mutex);
++	}
+ err_pool_free:
+ 	poolm->ops->free(poolm, shm);
+ err_kfree:
+@@ -194,31 +185,8 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,
+ 	tee_device_put(teedev);
+ 	return ret;
+ }
+-
+-/**
+- * tee_shm_alloc() - Allocate shared memory
+- * @ctx:	Context that allocates the shared memory
+- * @size:	Requested size of shared memory
+- * @flags:	Flags setting properties for the requested shared memory.
+- *
+- * Memory allocated as global shared memory is automatically freed when the
+- * TEE file pointer is closed. The @flags field uses the bits defined by
+- * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
+- * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
+- * associated with a dma-buf handle, else driver private memory.
+- */
+-struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+-{
+-	return __tee_shm_alloc(ctx, ctx->teedev, size, flags);
+-}
+ EXPORT_SYMBOL_GPL(tee_shm_alloc);
+ 
+-struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size)
+-{
+-	return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED);
+-}
+-EXPORT_SYMBOL_GPL(tee_shm_priv_alloc);
+-
+ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
+ 				 size_t length, u32 flags)
+ {
+@@ -251,7 +219,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
+ 	}
+ 
+ 	shm->flags = flags | TEE_SHM_REGISTER;
+-	shm->teedev = teedev;
+ 	shm->ctx = ctx;
+ 	shm->id = -1;
+ 	addr = untagged_addr(addr);
+@@ -307,10 +274,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
+ 		}
+ 	}
+ 
+-	mutex_lock(&teedev->mutex);
+-	list_add_tail(&shm->link, &ctx->list_shm);
+-	mutex_unlock(&teedev->mutex);
+-
+ 	return shm;
+ err:
+ 	if (shm) {
+diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
+index 545a57f61a5e..407c27c11b2b 100644
+--- a/include/linux/tee_drv.h
++++ b/include/linux/tee_drv.h
+@@ -49,7 +49,6 @@ struct tee_shm_pool;
+  */
+ struct tee_context {
+ 	struct tee_device *teedev;
+-	struct list_head list_shm;
+ 	void *data;
+ 	struct kref refcount;
+ 	bool releasing;
+@@ -184,9 +183,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
+ 
+ /**
+  * struct tee_shm - shared memory object
+- * @teedev:	device used to allocate the object
+- * @ctx:	context using the object, if NULL the context is gone
+- * @link	link element
++ * @ctx:	context using the object
+  * @paddr:	physical address of the shared memory
+  * @kaddr:	virtual address of the shared memory
+  * @size:	size of shared memory
+@@ -195,15 +192,17 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
+  * @num_pages:	number of locked pages
+  * @dmabuf:	dmabuf used to for exporting to user space
+  * @flags:	defined by TEE_SHM_* in tee_drv.h
+- * @id:		unique id of a shared memory object on this device
++ * @id:		unique id of a shared memory object on this device, shared
++ *		with user space
++ * @sec_world_id:
++ *		secure world assigned id of this shared memory object, not
++ *		used by all drivers
+  *
+  * This pool is only supposed to be accessed directly from the TEE
+  * subsystem and from drivers that implements their own shm pool manager.
+  */
+ struct tee_shm {
+-	struct tee_device *teedev;
+ 	struct tee_context *ctx;
+-	struct list_head link;
+ 	phys_addr_t paddr;
+ 	void *kaddr;
+ 	size_t size;
+@@ -213,6 +212,7 @@ struct tee_shm {
+ 	struct dma_buf *dmabuf;
+ 	u32 flags;
+ 	int id;
++	u64 sec_world_id;
+ };
+ 
+ /**
+@@ -334,18 +334,6 @@ void *tee_get_drvdata(struct tee_device *teedev);
+  */
+ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
+ 
+-/**
+- * tee_shm_priv_alloc() - Allocate shared memory privately
+- * @dev:	Device that allocates the shared memory
+- * @size:	Requested size of shared memory
+- *
+- * Allocates shared memory buffer that is not associated with any client
+- * context. Such buffers are owned by TEE driver and used for internal calls.
+- *
+- * @returns a pointer to 'struct tee_shm'
+- */
+-struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size);
+-
+ /**
+  * tee_shm_register() - Register shared memory buffer
+  * @ctx:	Context that registers the shared memory
+-- 
+2.26.2
+
diff --git a/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch
new file mode 100644
index 0000000..ad2c945
--- /dev/null
+++ b/meta-arm-bsp/recipes-kernel/linux/linux-arm64-ack-5.4/tc0/0013-tee-optee-fix-mem-handle-removal-in-ffa_shm_unregist.patch
@@ -0,0 +1,51 @@
+From 957e0145899813017a6a2b7f863a4a2b4e4b75aa Mon Sep 17 00:00:00 2001
+From: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Date: Tue, 5 Jan 2021 09:27:41 +0000
+Subject: [PATCH] tee: optee: fix mem handle removal in ffa_shm_unregister
+
+Remove ffa memory handle before calling mem_reclaim. This enables the
+handle to be re-used by another thread once mem_claim for that handle
+is completed.
+
+Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
+Change-Id: I7294bd71f2bbc28514eaa09ae757dd216bc7df45
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+---
+ drivers/tee/optee/call.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
+index ac89ab42a43f..9c9480add0b5 100644
+--- a/drivers/tee/optee/call.c
++++ b/drivers/tee/optee/call.c
+@@ -843,6 +843,10 @@ int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
+ {
+ 	struct optee *optee = tee_get_drvdata(ctx->teedev);
+ 	int rc = 0;
++	u64 handle = shm->sec_world_id;
++
++	optee_shm_rem_ffa_handle(optee, handle);
++	shm->sec_world_id = 0;
+ 
+ 	/*
+ 	 * We're skipping the OPTEE_FFA_YIELDING_CALL_UNREGISTER_SHM call
+@@ -850,14 +854,10 @@ int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
+ 	 * this ID.
+ 	 */
+ 
+-	rc = optee->ffa.ops->mem_reclaim(shm->sec_world_id, 0);
++	rc = optee->ffa.ops->mem_reclaim(handle, 0);
+ 	if (rc)
+ 		pr_err("mem_reclain: %d", rc);
+ 
+-	optee_shm_rem_ffa_handle(optee, shm->sec_world_id);
+-
+-	shm->sec_world_id = 0;
+-
+ 	return rc;
+ }
+ #endif /*CONFIG_ARM_FFA_TRANSPORT*/
+-- 
+2.26.2
+
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 10/10] arm-bsp/tc0: Enable spmd and SEL2 SPMC with optee as SEL1 SP
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (7 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 09/10] arm-bsp/linux: add ffa transport in optee " Arunachalam Ganapathy
@ 2021-01-12 15:20 ` Arunachalam Ganapathy
  2021-01-14 19:23 ` [meta-arm] [PATCH 01/10] arm: Add hafnium support Jon Mason
  9 siblings, 0 replies; 11+ messages in thread
From: Arunachalam Ganapathy @ 2021-01-12 15:20 UTC (permalink / raw)
  To: meta-arm; +Cc: nd, Arunachalam Ganapathy

- Set SPD to spmd with SEL2 SPMC. Set optee as SP
- Assign SP layout and spmc manifest file that corresponds to optee
- Move TF-A version from 2.3 to 2.4

Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
Change-Id: I3da3bf7f95ba42716b731f92e2cdfb928b1ab77f
---
 meta-arm-bsp/conf/machine/tc0.conf            |  3 +--
 .../trusted-firmware-a-tc0.inc                | 19 +++++++++++++------
 .../trusted-firmware-a_2.3.bbappend           |  1 -
 .../trusted-firmware-a_2.4.bbappend           |  1 +
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/meta-arm-bsp/conf/machine/tc0.conf b/meta-arm-bsp/conf/machine/tc0.conf
index 6c366da..eda3324 100644
--- a/meta-arm-bsp/conf/machine/tc0.conf
+++ b/meta-arm-bsp/conf/machine/tc0.conf
@@ -26,9 +26,8 @@ UBOOT_SIGN_KEYNAME = "dev_key"
 UBOOT_SIGN_KEYDIR = "${DEPLOY_DIR_IMAGE}/keys"
 FIT_GENERATE_KEYS = "1"
 
-# Trusted firmware A v2.3
 PREFERRED_PROVIDER_virtual/trusted-firmware-a ?= "trusted-firmware-a"
-PREFERRED_VERSION_trusted-firmware-a ?= "2.3%"
+PREFERRED_VERSION_trusted-firmware-a ?= "2.4%"
 
 PREFERRED_PROVIDER_virtual/kernel ?= "linux-arm64-ack"
 PREFERRED_VERSION_linux-arm64-ack ?= "5.4"
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc0.inc b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc0.inc
index 8d98937..bb12ba4 100644
--- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc0.inc
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a-tc0.inc
@@ -1,10 +1,8 @@
-# TCO specific TFA configuration
+# TC0 specific TFA configuration
 
-# Intermediate SHA with 2.3 baseline version
-SRCREV_tfa = "16796a25fefc4ecf780211bf554d3b8dc5436fa4"
-
-# This is incorporated into the SRCREV above
-SRC_URI_remove = "file://0001-fdts-a5ds-Fix-for-the-system-timer-issue.patch"
+# Intermediate SHA with 2.4 baseline version, required for OP-TEE SP
+SRCREV_tfa = "b153ce0391012e9228b807815a65fa0dc514cf77"
+PV = "2.4+git${SRCPV}"
 
 DEPENDS += "scp-firmware"
 
@@ -17,6 +15,15 @@ TFA_INSTALL_TARGET = "bl1 fip"
 TFA_MBEDTLS = "1"
 TFA_DEBUG = "1"
 
+TFA_SPD = "spmd"
+TFA_SPMD_SPM_AT_SEL2 = "1"
+
+# Set optee as SP. Set spmc manifest and sp layout file to optee
+DEPENDS += "optee-os"
+
+TFA_SP_LAYOUT_FILE = "${RECIPE_SYSROOT}/lib/firmware/sp_layout.json"
+TFA_ARM_SPMC_MANIFEST_DTS = "plat/arm/board/tc0/fdts/tc0_spmc_optee_sp_manifest.dts"
+
 EXTRA_OEMAKE += "SCP_BL2=${RECIPE_SYSROOT}/firmware/scp_ramfw.bin"
 EXTRA_OEMAKE += "TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 ARM_ROTPK_LOCATION=devel_rsa \
                      ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem"
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.3.bbappend b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.3.bbappend
index f1908f8..0535278 100644
--- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.3.bbappend
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.3.bbappend
@@ -1,7 +1,6 @@
 # Machine specific TFAs
 
 MACHINE_TFA_REQUIRE ?= ""
-MACHINE_TFA_REQUIRE_tc0 = "trusted-firmware-a-tc0.inc"
 MACHINE_TFA_REQUIRE_corstone500 = "trusted-firmware-a-corstone500.inc"
 MACHINE_TFA_REQUIRE_juno = "trusted-firmware-a-juno.inc"
 MACHINE_TFA_REQUIRE_corstone700 = "trusted-firmware-a-corstone700.inc"
diff --git a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.4.bbappend b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.4.bbappend
index 944dd7a..8087f39 100644
--- a/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.4.bbappend
+++ b/meta-arm-bsp/recipes-bsp/trusted-firmware-a/trusted-firmware-a_2.4.bbappend
@@ -4,5 +4,6 @@ MACHINE_TFA_REQUIRE ?= ""
 MACHINE_TFA_REQUIRE_fvp-base = "trusted-firmware-a-fvp.inc"
 MACHINE_TFA_REQUIRE_fvp-base-arm32 = "trusted-firmware-a-fvp-arm32.inc"
 MACHINE_TFA_REQUIRE_n1sdp = "trusted-firmware-a-n1sdp.inc"
+MACHINE_TFA_REQUIRE_tc0 = "trusted-firmware-a-tc0.inc"
 
 require ${MACHINE_TFA_REQUIRE}
-- 
2.29.2


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [meta-arm] [PATCH 01/10] arm: Add hafnium support
  2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
                   ` (8 preceding siblings ...)
  2021-01-12 15:20 ` [PATCH 10/10] arm-bsp/tc0: Enable spmd and SEL2 SPMC with optee as SEL1 SP Arunachalam Ganapathy
@ 2021-01-14 19:23 ` Jon Mason
  9 siblings, 0 replies; 11+ messages in thread
From: Jon Mason @ 2021-01-14 19:23 UTC (permalink / raw)
  To: Arunachalam Ganapathy; +Cc: meta-arm, nd

On Tue, Jan 12, 2021 at 03:20:40PM +0000, Arunachalam Ganapathy wrote:
> Initial recipe for hafnium[1]. This enables build for reference Secure
> Partition Manager (SPM) for systems that implement the Armv8.4-A
> Secure-EL2 extension.
> 
> Link: [1] https://www.trustedfirmware.org/projects/hafnium/
> 
> Signed-off-by: Arunachalam Ganapathy <arunachalam.ganapathy@arm.com>
> Change-Id: Ib256d8ca03c94131e308d962d786d5d6a656c256
> ---

Series pulled into master.

Thanks,
Jon

>  meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb | 74 +++++++++++++++++++++
>  1 file changed, 74 insertions(+)
>  create mode 100644 meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
> 
> diff --git a/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb b/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
> new file mode 100644
> index 0000000..3a52599
> --- /dev/null
> +++ b/meta-arm/recipes-bsp/hafnium/hafnium_2.4.bb
> @@ -0,0 +1,74 @@
> +SUMMARY = "Hafnium"
> +DESCRIPTION = "A reference Secure Partition Manager (SPM) for systems that implement the Armv8.4-A Secure-EL2 extension"
> +LICENSE = "BSD-3-Clause & GPLv2"
> +LIC_FILES_CHKSUM = "file://LICENSE;md5=782b40c14bad5294672c500501edc103"
> +
> +PACKAGE_ARCH = "${MACHINE_ARCH}"
> +
> +inherit deploy python3native
> +
> +SRC_URI = "gitsm://git.trustedfirmware.org/hafnium/hafnium.git;protocol=https"
> +SRCREV = "410a3acaf669c12d41fb4c57fcaf3ecee6fdba61"
> +S = "${WORKDIR}/git"
> +
> +COMPATIBLE_MACHINE ?= "invalid"
> +
> +# Default build 'reference'
> +HAFNIUM_PROJECT ?= "reference"
> +
> +# Platform must be set for each machine
> +HAFNIUM_PLATFORM ?= "invalid"
> +
> +# hafnium build directory
> +# Append _clang as the build rule in hafnium adds this to the platform name.
> +HAFNIUM_BUILD_DIR_PLAT = "out/${HAFNIUM_PROJECT}/${HAFNIUM_PLATFORM}_clang"
> +
> +# do_deploy will install everything listed in this variable. It is set by
> +# default to hafnium
> +HAFNIUM_INSTALL_TARGET ?= "hafnium"
> +
> +DEPENDS = "bison-native bc-native"
> +
> +# set project to build
> +EXTRA_OEMAKE += "PROJECT=${HAFNIUM_PROJECT}"
> +
> +do_compile_prepend() {
> +    # Hafnium expects 'python'. Create symlink python to python3
> +    real=$(which ${PYTHON})
> +    ln -snf $real $(dirname $real)/python
> +}
> +
> +do_install() {
> +    install -d -m 755 ${D}/firmware
> +    for bldfile in ${HAFNIUM_INSTALL_TARGET}; do
> +        processed="0"
> +        if [ -f ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.bin ]; then
> +            echo "Install $bldfile.bin"
> +            install -m 0755 ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.bin \
> +                ${D}/firmware/$bldfile-${HAFNIUM_PLATFORM}.bin
> +            ln -sf $bldfile-${HAFNIUM_PLATFORM}.bin ${D}/firmware/$bldfile.bin
> +            processed="1"
> +        fi
> +        if [ -f ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.elf ]; then
> +            echo "Install $bldfile.elf"
> +            install -m 0755 ${S}/${HAFNIUM_BUILD_DIR_PLAT}/$bldfile.elf \
> +                ${D}/firmware/$bldfile-${HAFNIUM_PLATFORM}.elf
> +            ln -sf $bldfile-${HAFNIUM_PLATFORM}.elf ${D}/firmware/$bldfile.elf
> +            processed="1"
> +        fi
> +        if [ "$processed" = "0" ]; then
> +            bberror "Unsupported HAFNIUM_INSTALL_TARGET target $bldfile"
> +            exit 1
> +        fi
> +    done
> +}
> +
> +FILES_${PN} = "/firmware"
> +SYSROOT_DIRS += "/firmware"
> +# skip QA tests: {'ldflags'}
> +INSANE_SKIP_${PN} = "ldflags"
> +
> +do_deploy() {
> +    cp -rf ${D}/firmware/* ${DEPLOYDIR}/
> +}
> +addtask deploy after do_install
> -- 
> 2.29.2
> 

> 
> 
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-01-14 19:24 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-12 15:20 [PATCH 01/10] arm: Add hafnium support arunachalam.ganapathy
2021-01-12 15:20 ` [PATCH 02/10] arm/trusted-firmware-a: Add support for spmd build option arunachalam.ganapathy
2021-01-12 15:20 ` [PATCH 03/10] arm-bsp/tc0: Add hafnium support Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 04/10] arm-bsp/tc0: Add support for optee Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 05/10] arm-bsp/tc0: Add tc0 platform support patches " Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 06/10] arm-bsp/tc0: Enable optee core with SPMC at SEL2 Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 07/10] arm-bsp/linux: add ffa driver to TC0 Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 08/10] arm-bsp/linux: enable ffa driver for TC0 Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 09/10] arm-bsp/linux: add ffa transport in optee " Arunachalam Ganapathy
2021-01-12 15:20 ` [PATCH 10/10] arm-bsp/tc0: Enable spmd and SEL2 SPMC with optee as SEL1 SP Arunachalam Ganapathy
2021-01-14 19:23 ` [meta-arm] [PATCH 01/10] arm: Add hafnium support Jon Mason

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.