Create separate path for SMC forwarding

This is the first stage of creating an SMC forwarding path based on
the manifest.

Currently none of the SMCs are forwarded, which maintains existing behavior.

Bug: 132421503
Change-Id: I1c3257b83346d47ff1e71db3898b9b85be14a043
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 4cf8118..7ee74d1 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -247,21 +247,60 @@
 	write_msr(hcr_el2, hcr_el2);
 }
 
-static bool smc_handler(struct vcpu *vcpu, uint32_t func, uintreg_t arg0,
-			uintreg_t arg1, uintreg_t arg2, uintreg_t *ret,
-			struct vcpu **next)
+static bool smc_check_client_privileges(const struct vcpu *vcpu)
 {
-	if (psci_handler(vcpu, func, arg0, arg1, arg2, ret, next)) {
+	(void)vcpu; /*UNUSED*/
+
+	/*
+	 * TODO(b/132421503): Check for privileges based on manifest.
+	 * Currently returns false, which maintains existing behavior.
+	 */
+
+	return false;
+}
+
+/**
+ * Applies SMC access control according to manifest.
+ * Forwards the call if access is granted.
+ * Returns true if call is forwarded.
+ */
+static bool smc_forwarder(const struct vcpu *vcpu, smc_res_t *ret)
+{
+	uint32_t func = vcpu->regs.r[0];
+	/* TODO(b/132421503): obtain vmid according to new scheme. */
+	uint32_t client_id = vcpu->vm->id;
+
+	if (smc_check_client_privileges(vcpu)) {
+		*ret = smc64(func, vcpu->regs.r[1], vcpu->regs.r[2],
+			     vcpu->regs.r[3], vcpu->regs.r[4], vcpu->regs.r[5],
+			     vcpu->regs.r[6], client_id);
+		return true;
+	}
+
+	return false;
+}
+
+/**
+ * Processes SMC instruction calls.
+ */
+static bool smc_handler(struct vcpu *vcpu, smc_res_t *ret, struct vcpu **next)
+{
+	uint32_t func = vcpu->regs.r[0];
+
+	if (psci_handler(vcpu, func, vcpu->regs.r[1], vcpu->regs.r[2],
+			 vcpu->regs.r[3], &(ret->res0), next)) {
+		/* SMC PSCI calls are processed by the PSCI handler. */
 		return true;
 	}
 
 	switch (func & ~SMCCC_CONVENTION_MASK) {
 	case HF_DEBUG_LOG:
-		*ret = api_debug_log(arg0, vcpu);
+		api_debug_log(vcpu->regs.r[1], vcpu);
 		return true;
 	}
 
-	return false;
+	/* Remaining SMC calls need to be forwarded. */
+	return smc_forwarder(vcpu, ret);
 }
 
 struct hvc_handler_return hvc_handler(uintreg_t arg0, uintreg_t arg1,
@@ -471,19 +510,21 @@
 
 	case 0x17: /* EC = 010111, SMC instruction. */ {
 		uintreg_t smc_pc = vcpu->regs.pc;
-		uintreg_t ret;
+		smc_res_t ret;
 		struct vcpu *next = NULL;
 
-		if (!smc_handler(vcpu, vcpu->regs.r[0], vcpu->regs.r[1],
-				 vcpu->regs.r[2], vcpu->regs.r[3], &ret,
-				 &next)) {
+		if (!smc_handler(vcpu, &ret, &next)) {
+			/* TODO(b/132421503): handle SMC forward rejection  */
 			dlog("Unsupported SMC call: %#x\n", vcpu->regs.r[0]);
-			ret = PSCI_ERROR_NOT_SUPPORTED;
+			ret.res0 = PSCI_ERROR_NOT_SUPPORTED;
 		}
 
 		/* Skip the SMC instruction. */
 		vcpu->regs.pc = smc_pc + (esr & (1u << 25) ? 4 : 2);
-		vcpu->regs.r[0] = ret;
+		vcpu->regs.r[0] = ret.res0;
+		vcpu->regs.r[1] = ret.res1;
+		vcpu->regs.r[2] = ret.res2;
+		vcpu->regs.r[3] = ret.res3;
 		return next;
 	}