FF-A: secondary EC cold boot

When the SPMC boots, all Secure Partitions are initialized
on their primary Execution Context. A Secure Partition calls
FFA_SECONDARY_EP_REGISTER at virtual FF-A instance from
its first EC passing the entry point address for secondary
ECs. A secondary EC is first resumed either upon invocation
of PSCI_CPU_ON from the NWd to which a SP is registered
(currently the first SP) or by ffa_run invocation.

Change-Id: Ic6050af16d4081ca31729744995fbb999b170e11
Signed-off-by: Max Shvetsov <maksims.svecovs@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/api.c b/src/api.c
index 75a06b7..fdb395f 100644
--- a/src/api.c
+++ b/src/api.c
@@ -545,6 +545,8 @@
 static bool api_vcpu_prepare_run(const struct vcpu *current, struct vcpu *vcpu,
 				 struct ffa_value *run_ret)
 {
+	struct vcpu_locked vcpu_locked;
+	struct vm_locked vm_locked;
 	bool need_vm_lock;
 	bool ret;
 
@@ -556,14 +558,24 @@
 	 * dependencies in the common run case meaning the sensitive context
 	 * switch performance is consistent.
 	 */
-	sl_lock(&vcpu->lock);
+	vcpu_locked = vcpu_lock(vcpu);
+
+#if SECURE_WORLD == 1
+
+	if (vcpu_secondary_reset_and_start(vcpu_locked, vcpu->vm->secondary_ep,
+					   0)) {
+		dlog_verbose("%s secondary cold boot vmid %#x vcpu id %#x\n",
+			     __func__, vcpu->vm->id, current->cpu->id);
+	}
+
+#endif
 
 	/* The VM needs to be locked to deliver mailbox messages. */
 	need_vm_lock = vcpu->state == VCPU_STATE_BLOCKED_MAILBOX;
 	if (need_vm_lock) {
-		sl_unlock(&vcpu->lock);
-		sl_lock(&vcpu->vm->lock);
-		sl_lock(&vcpu->lock);
+		vcpu_unlock(&vcpu_locked);
+		vm_locked = vm_lock(vcpu->vm);
+		vcpu_locked = vcpu_lock(vcpu);
 	}
 
 	/*
@@ -671,9 +683,9 @@
 	ret = true;
 
 out:
-	sl_unlock(&vcpu->lock);
+	vcpu_unlock(&vcpu_locked);
 	if (need_vm_lock) {
-		sl_unlock(&vcpu->vm->lock);
+		vm_unlock(&vm_locked);
 	}
 
 	return ret;
@@ -2278,3 +2290,15 @@
 
 	return ret;
 }
+
+struct ffa_value api_ffa_secondary_ep_register(ipaddr_t entry_point,
+					       struct vcpu *current)
+{
+	struct vm_locked vm_locked;
+
+	vm_locked = vm_lock(current->vm);
+	vm_locked.vm->secondary_ep = entry_point;
+	vm_unlock(&vm_locked);
+
+	return (struct ffa_value){.func = FFA_SUCCESS_32};
+}