Make smc_handler follow same interface as hvc_handler.

Change-Id: I0579bd0af00b3894566287aad5403cf26d5b99d7
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 7b9ac24..fd490ff 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -284,14 +284,13 @@
  * Applies SMC access control according to manifest and forwards the call if
  * access is granted.
  */
-static void smc_forwarder(const struct vcpu *vcpu, struct spci_value *ret)
+static void smc_forwarder(const struct vm *vm, struct spci_value *args)
 {
-	uint32_t func = vcpu->regs.r[0];
-	uint32_t client_id = vcpu->vm->id;
-	uintreg_t arg7;
+	uint32_t client_id = vm->id;
+	uintreg_t arg7 = args->arg7;
 
-	if (smc_is_blocked(vcpu->vm, func)) {
-		ret->func = SMCCC_ERROR_UNKNOWN;
+	if (smc_is_blocked(vm, args->func)) {
+		args->func = SMCCC_ERROR_UNKNOWN;
 		return;
 	}
 
@@ -300,10 +299,9 @@
 	 * else (currently unspecified) that the client may have passed in the
 	 * upper bits.
 	 */
-	arg7 = client_id | (vcpu->regs.r[7] & ~CLIENT_ID_MASK);
-	*ret = smc_forward(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], arg7);
+	args->arg7 = client_id | (arg7 & ~CLIENT_ID_MASK);
+	*args = smc_forward(args->func, args->arg1, args->arg2, args->arg3,
+			    args->arg4, args->arg5, args->arg6, args->arg7);
 
 	/*
 	 * Preserve the value passed by the caller, rather than the client_id we
@@ -311,7 +309,7 @@
 	 * may be in x7, but the SMCs that we are forwarding are legacy calls
 	 * from before SMCCC 1.2 so won't have more than 4 return values anyway.
 	 */
-	ret->arg7 = vcpu->regs.r[7];
+	args->arg7 = arg7;
 }
 
 static bool spci_handler(struct spci_value *args, struct vcpu **next)
@@ -399,8 +397,7 @@
 /**
  * Processes SMC instruction calls.
  */
-static void smc_handler(struct vcpu *vcpu, struct spci_value *ret,
-			struct vcpu **next)
+static struct vcpu *smc_handler(struct vcpu *vcpu)
 {
 	struct spci_value args = {
 		.func = vcpu->regs.r[0],
@@ -412,25 +409,28 @@
 		.arg6 = vcpu->regs.r[6],
 		.arg7 = vcpu->regs.r[7],
 	};
+	struct vcpu *next = NULL;
 
 	if (psci_handler(vcpu, args.func, args.arg1, args.arg2, args.arg3,
-			 &ret->func, next)) {
-		return;
+			 &vcpu->regs.r[0], &next)) {
+		return next;
 	}
 
-	if (spci_handler(&args, next)) {
-		*ret = args;
-		update_vi(*next);
-		return;
+	if (spci_handler(&args, &next)) {
+		arch_regs_set_retval(&vcpu->regs, args);
+		update_vi(next);
+		return next;
 	}
 
 	switch (args.func & ~SMCCC_CONVENTION_MASK) {
 	case HF_DEBUG_LOG:
-		ret->func = api_debug_log(args.arg1, vcpu);
-		return;
+		vcpu->regs.r[0] = api_debug_log(args.arg1, vcpu);
+		return next;
 	}
 
-	smc_forwarder(vcpu, ret);
+	smc_forwarder(vcpu->vm, &args);
+	arch_regs_set_retval(&vcpu->regs, args);
+	return next;
 }
 
 struct vcpu *hvc_handler(struct vcpu *vcpu)
@@ -603,17 +603,11 @@
 
 	case 0x17: /* EC = 010111, SMC instruction. */ {
 		uintreg_t smc_pc = vcpu->regs.pc;
-		struct vcpu *next = NULL;
-		struct spci_value ret = {.arg4 = vcpu->regs.r[4],
-					 .arg5 = vcpu->regs.r[5],
-					 .arg6 = vcpu->regs.r[6],
-					 .arg7 = vcpu->regs.r[7]};
-
-		smc_handler(vcpu, &ret, &next);
+		struct vcpu *next = smc_handler(vcpu);
 
 		/* Skip the SMC instruction. */
 		vcpu->regs.pc = smc_pc + GET_NEXT_PC_INC(esr);
-		arch_regs_set_retval(&vcpu->regs, ret);
+
 		return next;
 	}
 
diff --git a/test/vmapi/arch/aarch64/smc_whitelist.c b/test/vmapi/arch/aarch64/smc_whitelist.c
index 044df7e..718be64 100644
--- a/test/vmapi/arch/aarch64/smc_whitelist.c
+++ b/test/vmapi/arch/aarch64/smc_whitelist.c
@@ -28,9 +28,9 @@
 		0x6666666666666666, 0x77777777);
 
 	EXPECT_EQ(smc_res.func, SMCCC_ERROR_UNKNOWN);
-	EXPECT_EQ(smc_res.arg1, 0);
-	EXPECT_EQ(smc_res.arg2, 0);
-	EXPECT_EQ(smc_res.arg3, 0);
+	EXPECT_EQ(smc_res.arg1, UINT64_C(0x1111111111111111));
+	EXPECT_EQ(smc_res.arg2, UINT64_C(0x2222222222222222));
+	EXPECT_EQ(smc_res.arg3, UINT64_C(0x3333333333333333));
 	EXPECT_EQ(smc_res.arg4, UINT64_C(0x4444444444444444));
 	EXPECT_EQ(smc_res.arg5, UINT64_C(0x5555555555555555));
 	EXPECT_EQ(smc_res.arg6, UINT64_C(0x6666666666666666));
diff --git a/test/vmapi/arch/aarch64/smccc.c b/test/vmapi/arch/aarch64/smccc.c
index b078e27..e79646a 100644
--- a/test/vmapi/arch/aarch64/smccc.c
+++ b/test/vmapi/arch/aarch64/smccc.c
@@ -14,12 +14,44 @@
  * limitations under the License.
  */
 
+#include <stdint.h>
+
 #include "vmapi/hf/call.h"
+#include "vmapi/hf/spci.h"
 
 #include "hftest.h"
 #include "smc.h"
 
-TEST(smccc, hf_debug_log_zero_or_unchanged)
+static struct spci_value hvc(uint32_t func, uint64_t arg0, uint64_t arg1,
+			     uint64_t arg2, uint64_t arg3, uint64_t arg4,
+			     uint64_t arg5, uint32_t caller_id)
+{
+	register uint64_t r0 __asm__("x0") = func;
+	register uint64_t r1 __asm__("x1") = arg0;
+	register uint64_t r2 __asm__("x2") = arg1;
+	register uint64_t r3 __asm__("x3") = arg2;
+	register uint64_t r4 __asm__("x4") = arg3;
+	register uint64_t r5 __asm__("x5") = arg4;
+	register uint64_t r6 __asm__("x6") = arg5;
+	register uint64_t r7 __asm__("x7") = caller_id;
+
+	__asm__ volatile(
+		"hvc #0"
+		: /* Output registers, also used as inputs ('+' constraint). */
+		"+r"(r0), "+r"(r1), "+r"(r2), "+r"(r3), "+r"(r4), "+r"(r5),
+		"+r"(r6), "+r"(r7));
+
+	return (struct spci_value){.func = r0,
+				   .arg1 = r1,
+				   .arg2 = r2,
+				   .arg3 = r3,
+				   .arg4 = r4,
+				   .arg5 = r5,
+				   .arg6 = r6,
+				   .arg7 = r7};
+}
+
+TEST(smccc, hf_debug_log_smc_zero_or_unchanged)
 {
 	struct spci_value smc_res =
 		smc_forward(HF_DEBUG_LOG, '\n', 0x2222222222222222,
@@ -27,9 +59,26 @@
 			    0x5555555555555555, 0x6666666666666666, 0x77777777);
 
 	EXPECT_EQ(smc_res.func, 0);
-	EXPECT_EQ(smc_res.arg1, 0);
-	EXPECT_EQ(smc_res.arg2, 0);
-	EXPECT_EQ(smc_res.arg3, 0);
+	EXPECT_EQ(smc_res.arg1, '\n');
+	EXPECT_EQ(smc_res.arg2, UINT64_C(0x2222222222222222));
+	EXPECT_EQ(smc_res.arg3, UINT64_C(0x3333333333333333));
+	EXPECT_EQ(smc_res.arg4, UINT64_C(0x4444444444444444));
+	EXPECT_EQ(smc_res.arg5, UINT64_C(0x5555555555555555));
+	EXPECT_EQ(smc_res.arg6, UINT64_C(0x6666666666666666));
+	EXPECT_EQ(smc_res.arg7, UINT64_C(0x77777777));
+}
+
+TEST(smccc, hf_debug_log_hvc_zero_or_unchanged)
+{
+	struct spci_value smc_res =
+		hvc(HF_DEBUG_LOG, '\n', 0x2222222222222222, 0x3333333333333333,
+		    0x4444444444444444, 0x5555555555555555, 0x6666666666666666,
+		    0x77777777);
+
+	EXPECT_EQ(smc_res.func, 0);
+	EXPECT_EQ(smc_res.arg1, '\n');
+	EXPECT_EQ(smc_res.arg2, UINT64_C(0x2222222222222222));
+	EXPECT_EQ(smc_res.arg3, UINT64_C(0x3333333333333333));
 	EXPECT_EQ(smc_res.arg4, UINT64_C(0x4444444444444444));
 	EXPECT_EQ(smc_res.arg5, UINT64_C(0x5555555555555555));
 	EXPECT_EQ(smc_res.arg6, UINT64_C(0x6666666666666666));