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/hftest/power_mgmt.c b/src/arch/aarch64/hftest/power_mgmt.c
index 161c200..98977f5 100644
--- a/src/arch/aarch64/hftest/power_mgmt.c
+++ b/src/arch/aarch64/hftest/power_mgmt.c
@@ -74,7 +74,7 @@
 
 	/* Try to start the CPU. */
 	smc_res = smc32(PSCI_CPU_ON, id, (size_t)&vm_cpu_entry_raw, (size_t)&s,
-			0, 0, 0, 0);
+			0, 0, 0, SMCCC_CALLER_HYPERVISOR);
 	if (smc_res.res0 != PSCI_RETURN_SUCCESS) {
 		return false;
 	}
@@ -93,7 +93,7 @@
  */
 noreturn void cpu_stop(void)
 {
-	smc32(PSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, 0);
+	smc32(PSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
 	for (;;) {
 		/* This should never be reached. */
 	}
@@ -120,7 +120,7 @@
 	 * this is the case.
 	 */
 	smc_res = smc32(PSCI_AFFINITY_INFO, cpu_id, lowest_affinity_level, 0, 0,
-			0, 0, 0);
+			0, 0, SMCCC_CALLER_HYPERVISOR);
 	return smc_res.res0;
 }
 
@@ -129,7 +129,7 @@
  */
 noreturn void arch_power_off(void)
 {
-	smc32(PSCI_SYSTEM_OFF, 0, 0, 0, 0, 0, 0, 0);
+	smc32(PSCI_SYSTEM_OFF, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
 	for (;;) {
 		/* This should never be reached. */
 	}
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;
 	}
 
diff --git a/src/arch/aarch64/hypervisor/psci_handler.c b/src/arch/aarch64/hypervisor/psci_handler.c
index ad3447f..8df6ff6 100644
--- a/src/arch/aarch64/hypervisor/psci_handler.c
+++ b/src/arch/aarch64/hypervisor/psci_handler.c
@@ -37,7 +37,8 @@
 /* Performs arch specific boot time initialisation. */
 void arch_one_time_init(void)
 {
-	smc_res_t smc_res = smc32(PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0);
+	smc_res_t smc_res =
+		smc32(PSCI_VERSION, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
 
 	el3_psci_version = smc_res.res0;
 
@@ -103,7 +104,8 @@
 				*ret = 0;
 			} else {
 				/* PSCI 1.x only defines two feature bits. */
-				smc_res = smc32(func, arg0, 0, 0, 0, 0, 0, 0);
+				smc_res = smc32(func, arg0, 0, 0, 0, 0, 0,
+						SMCCC_CALLER_HYPERVISOR);
 				*ret = smc_res.res0 & 0x3;
 			}
 			break;
@@ -127,12 +129,14 @@
 		break;
 
 	case PSCI_SYSTEM_OFF:
-		smc32(PSCI_SYSTEM_OFF, 0, 0, 0, 0, 0, 0, 0);
+		smc32(PSCI_SYSTEM_OFF, 0, 0, 0, 0, 0, 0,
+		      SMCCC_CALLER_HYPERVISOR);
 		panic("System off failed");
 		break;
 
 	case PSCI_SYSTEM_RESET:
-		smc32(PSCI_SYSTEM_RESET, 0, 0, 0, 0, 0, 0, 0);
+		smc32(PSCI_SYSTEM_RESET, 0, 0, 0, 0, 0, 0,
+		      SMCCC_CALLER_HYPERVISOR);
 		panic("System reset failed");
 		break;
 
@@ -166,14 +170,15 @@
 		 */
 		arch_regs_set_pc_arg(&vcpu->regs, ipa_init(arg1), arg2);
 		smc_res = smc64(PSCI_CPU_SUSPEND, arg0, (uintreg_t)&cpu_entry,
-				(uintreg_t)vcpu->cpu, 0, 0, 0, 0);
+				(uintreg_t)vcpu->cpu, 0, 0, 0,
+				SMCCC_CALLER_HYPERVISOR);
 		*ret = smc_res.res0;
 		break;
 	}
 
 	case PSCI_CPU_OFF:
 		cpu_off(vcpu->cpu);
-		smc32(PSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, 0);
+		smc32(PSCI_CPU_OFF, 0, 0, 0, 0, 0, 0, SMCCC_CALLER_HYPERVISOR);
 		panic("CPU off failed");
 		break;
 
@@ -196,9 +201,9 @@
 		 * itself off).
 		 */
 		do {
-			smc_res =
-				smc64(PSCI_CPU_ON, arg0, (uintreg_t)&cpu_entry,
-				      (uintreg_t)c, 0, 0, 0, 0);
+			smc_res = smc64(PSCI_CPU_ON, arg0,
+					(uintreg_t)&cpu_entry, (uintreg_t)c, 0,
+					0, 0, SMCCC_CALLER_HYPERVISOR);
 			*ret = smc_res.res0;
 		} while (*ret == PSCI_ERROR_ALREADY_ON);
 
diff --git a/src/arch/aarch64/smc.h b/src/arch/aarch64/smc.h
index 8c00a30..96d7f20 100644
--- a/src/arch/aarch64/smc.h
+++ b/src/arch/aarch64/smc.h
@@ -36,6 +36,8 @@
 #define SMCCC_STANDARD_SECURE_SERVICE_CALL     0x04000000
 #define SMCCC_STANDARD_HYPERVISOR_SERVICE_CALL 0x05000000
 #define SMCCC_VENDOR_HYPERVISOR_SERVICE_CALL   0x06000000
+
+#define SMCCC_CALLER_HYPERVISOR   0x0
 /*
  * TODO: Trusted application call: 0x30000000 - 0x31000000
  * TODO: Trusted OS call: 0x32000000 - 0x3f000000