Using new-style return values for spci_version.

Bug: 132395846
Change-Id: I7d1a926b8dab526b3d8c3c6d06a8c136e5639e5e
diff --git a/driver/linux b/driver/linux
index d426b6c..4fef63d 160000
--- a/driver/linux
+++ b/driver/linux
@@ -1 +1 @@
-Subproject commit d426b6cb6d2bdde5b7d6c140141f739378d2ca95
+Subproject commit 4fef63db09b5f9157496fa414bda628c4b9ef47b
diff --git a/inc/hf/api.h b/inc/hf/api.h
index e041c96..7dcdad3 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -21,6 +21,7 @@
 #include "hf/vm.h"
 
 #include "vmapi/hf/call.h"
+#include "vmapi/hf/spci.h"
 
 void api_init(struct mpool *ppool);
 spci_vm_id_t api_vm_get_id(const struct vcpu *current);
@@ -57,7 +58,7 @@
 				struct vcpu **next);
 int32_t api_spci_msg_recv(bool block, struct vcpu *current, struct vcpu **next);
 int32_t api_spci_yield(struct vcpu *current, struct vcpu **next);
-int32_t api_spci_version(void);
+struct spci_value api_spci_version(void);
 spci_return_t api_spci_share_memory(struct vm_locked to_locked,
 				    struct vm_locked from_locked,
 				    struct spci_memory_region *memory_region,
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 9edc542..56bf012 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -47,6 +47,7 @@
  * mechanism to call to the hypervisor.
  */
 int64_t hf_call(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3);
+struct spci_value spci_call(struct spci_value args);
 
 /**
  * Returns the VM's own ID.
@@ -274,7 +275,7 @@
 }
 
 /** Obtains the Hafnium's version of the implemented SPCI specification. */
-static inline int64_t spci_version(void)
+static inline struct spci_value spci_version(void)
 {
-	return hf_call(SPCI_VERSION_32, 0, 0, 0);
+	return spci_call((struct spci_value){.func = SPCI_VERSION_32});
 }
diff --git a/inc/vmapi/hf/spci.h b/inc/vmapi/hf/spci.h
index 39fcaf1..0883038 100644
--- a/inc/vmapi/hf/spci.h
+++ b/inc/vmapi/hf/spci.h
@@ -182,6 +182,16 @@
 /** Return type of SPCI functions. */
 /* TODO: Reuse spci_return_t type on all SPCI functions declarations. */
 typedef int32_t spci_return_t;
+struct spci_value {
+	uint64_t func;
+	uint64_t arg1;
+	uint64_t arg2;
+	uint64_t arg3;
+	uint64_t arg4;
+	uint64_t arg5;
+	uint64_t arg6;
+	uint64_t arg7;
+};
 
 /** SPCI common message header. */
 struct spci_message {
diff --git a/src/api.c b/src/api.c
index ff56751..a605ac4 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1653,7 +1653,7 @@
 }
 
 /** Returns the version of the implemented SPCI specification. */
-int32_t api_spci_version(void)
+struct spci_value api_spci_version(void)
 {
 	/*
 	 * Ensure that both major and minor revision representation occupies at
@@ -1664,8 +1664,11 @@
 	static_assert(0x10000 > SPCI_VERSION_MINOR,
 		      "Minor revision representation take more than 16 bits.");
 
-	return (SPCI_VERSION_MAJOR << SPCI_VERSION_MAJOR_OFFSET) |
-	       SPCI_VERSION_MINOR;
+	struct spci_value ret = {
+		.func = SPCI_SUCCESS_32,
+		.arg1 = (SPCI_VERSION_MAJOR << SPCI_VERSION_MAJOR_OFFSET) |
+			SPCI_VERSION_MINOR};
+	return ret;
 }
 
 int64_t api_debug_log(char c, struct vcpu *current)
diff --git a/src/arch/aarch64/hftest/hf_call.c b/src/arch/aarch64/hftest/hf_call.c
index ee591f1..c8cfabe 100644
--- a/src/arch/aarch64/hftest/hf_call.c
+++ b/src/arch/aarch64/hftest/hf_call.c
@@ -15,6 +15,7 @@
  */
 
 #include "hf/call.h"
+#include "hf/spci.h"
 #include "hf/types.h"
 
 int64_t hf_call(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3)
@@ -34,3 +35,30 @@
 
 	return r0;
 }
+
+struct spci_value spci_call(struct spci_value args)
+{
+	register uint64_t r0 __asm__("x0") = args.func;
+	register uint64_t r1 __asm__("x1") = args.arg1;
+	register uint64_t r2 __asm__("x2") = args.arg2;
+	register uint64_t r3 __asm__("x3") = args.arg3;
+	register uint64_t r4 __asm__("x4") = args.arg3;
+	register uint64_t r5 __asm__("x5") = args.arg3;
+	register uint64_t r6 __asm__("x6") = args.arg3;
+	register uint64_t r7 __asm__("x7") = args.arg3;
+
+	__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};
+}
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index e72d69e..154610a 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -303,33 +303,23 @@
 	return false;
 }
 
-static bool spci_handler(uintreg_t func, uintreg_t arg1, uintreg_t arg2,
-			 uintreg_t arg3, uintreg_t arg4, uintreg_t arg5,
-			 uintreg_t arg6, uintreg_t arg7, uintreg_t *ret,
-			 struct vcpu **next)
+static bool spci_handler(struct spci_value *args, struct vcpu **next)
 {
-	(void)arg2;
-	(void)arg3;
-	(void)arg4;
-	(void)arg5;
-	(void)arg6;
-	(void)arg7;
-
-	switch (func & ~SMCCC_CONVENTION_MASK) {
+	switch (args->func & ~SMCCC_CONVENTION_MASK) {
 	case SPCI_VERSION_32:
-		*ret = api_spci_version();
+		*args = api_spci_version();
 		return true;
 	case SPCI_YIELD_32:
-		*ret = api_spci_yield(current(), next);
+		args->func = api_spci_yield(current(), next);
 		return true;
 	case SPCI_MSG_SEND_32:
-		*ret = api_spci_msg_send(arg1, current(), next);
+		args->func = api_spci_msg_send(args->arg1, current(), next);
 		return true;
 	case SPCI_MSG_WAIT_32:
-		*ret = api_spci_msg_recv(true, current(), next);
+		args->func = api_spci_msg_recv(true, current(), next);
 		return true;
 	case SPCI_MSG_POLL_32:
-		*ret = api_spci_msg_recv(false, current(), next);
+		args->func = api_spci_msg_recv(false, current(), next);
 		return true;
 	}
 
@@ -390,28 +380,37 @@
 
 struct vcpu *hvc_handler(struct vcpu *vcpu)
 {
-	uint32_t func = vcpu->regs.r[0];
-	uintreg_t arg1 = vcpu->regs.r[1];
-	uintreg_t arg2 = vcpu->regs.r[2];
-	uintreg_t arg3 = vcpu->regs.r[3];
-	uintreg_t arg4 = vcpu->regs.r[4];
-	uintreg_t arg5 = vcpu->regs.r[5];
-	uintreg_t arg6 = vcpu->regs.r[6];
-	uintreg_t arg7 = vcpu->regs.r[7];
+	struct spci_value args = {
+		.func = vcpu->regs.r[0],
+		.arg1 = vcpu->regs.r[1],
+		.arg2 = vcpu->regs.r[2],
+		.arg3 = vcpu->regs.r[3],
+		.arg4 = vcpu->regs.r[4],
+		.arg5 = vcpu->regs.r[5],
+		.arg6 = vcpu->regs.r[6],
+		.arg7 = vcpu->regs.r[7],
+	};
 	struct vcpu *next = NULL;
 
-	if (psci_handler(vcpu, func, arg1, arg2, arg3, &vcpu->regs.r[0],
-			 &next)) {
+	if (psci_handler(vcpu, args.func, args.arg1, args.arg2, args.arg3,
+			 &vcpu->regs.r[0], &next)) {
 		return next;
 	}
 
-	if (spci_handler(func, arg1, arg2, arg3, arg4, arg5, arg6, arg7,
-			 &vcpu->regs.r[0], &next)) {
+	if (spci_handler(&args, &next)) {
+		vcpu->regs.r[0] = args.func;
+		vcpu->regs.r[1] = args.arg1;
+		vcpu->regs.r[2] = args.arg2;
+		vcpu->regs.r[3] = args.arg3;
+		vcpu->regs.r[4] = args.arg4;
+		vcpu->regs.r[5] = args.arg5;
+		vcpu->regs.r[6] = args.arg6;
+		vcpu->regs.r[7] = args.arg7;
 		update_vi(next);
 		return next;
 	}
 
-	switch (func) {
+	switch (args.func) {
 	case HF_VM_GET_ID:
 		vcpu->regs.r[0] = api_vm_get_id(vcpu);
 		break;
@@ -421,17 +420,17 @@
 		break;
 
 	case HF_VCPU_GET_COUNT:
-		vcpu->regs.r[0] = api_vcpu_get_count(arg1, vcpu);
+		vcpu->regs.r[0] = api_vcpu_get_count(args.arg1, vcpu);
 		break;
 
 	case HF_VCPU_RUN:
 		vcpu->regs.r[0] = hf_vcpu_run_return_encode(
-			api_vcpu_run(arg1, arg2, vcpu, &next));
+			api_vcpu_run(args.arg1, args.arg2, vcpu, &next));
 		break;
 
 	case HF_VM_CONFIGURE:
-		vcpu->regs.r[0] = api_vm_configure(ipa_init(arg1),
-						   ipa_init(arg2), vcpu, &next);
+		vcpu->regs.r[0] = api_vm_configure(
+			ipa_init(args.arg1), ipa_init(args.arg2), vcpu, &next);
 		break;
 
 	case HF_MAILBOX_CLEAR:
@@ -443,11 +442,12 @@
 		break;
 
 	case HF_MAILBOX_WAITER_GET:
-		vcpu->regs.r[0] = api_mailbox_waiter_get(arg1, vcpu);
+		vcpu->regs.r[0] = api_mailbox_waiter_get(args.arg1, vcpu);
 		break;
 
 	case HF_INTERRUPT_ENABLE:
-		vcpu->regs.r[0] = api_interrupt_enable(arg1, arg2, vcpu);
+		vcpu->regs.r[0] =
+			api_interrupt_enable(args.arg1, args.arg2, vcpu);
 		break;
 
 	case HF_INTERRUPT_GET:
@@ -455,18 +455,18 @@
 		break;
 
 	case HF_INTERRUPT_INJECT:
-		vcpu->regs.r[0] =
-			api_interrupt_inject(arg1, arg2, arg3, vcpu, &next);
+		vcpu->regs.r[0] = api_interrupt_inject(args.arg1, args.arg2,
+						       args.arg3, vcpu, &next);
 		break;
 
 	case HF_SHARE_MEMORY:
-		vcpu->regs.r[0] =
-			api_share_memory(arg1 >> 32, ipa_init(arg2), arg3,
-					 arg1 & 0xffffffff, vcpu);
+		vcpu->regs.r[0] = api_share_memory(
+			args.arg1 >> 32, ipa_init(args.arg2), args.arg3,
+			args.arg1 & 0xffffffff, vcpu);
 		break;
 
 	case HF_DEBUG_LOG:
-		vcpu->regs.r[0] = api_debug_log(arg1, vcpu);
+		vcpu->regs.r[0] = api_debug_log(args.arg1, vcpu);
 		break;
 
 	default:
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 45cbd52..3ed4186 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -153,7 +153,9 @@
 	const int32_t current_version =
 		(major_revision << major_revision_offset) | minor_revision;
 
-	EXPECT_EQ(spci_version(), current_version);
+	struct spci_value ret = spci_version();
+	EXPECT_EQ(ret.func, SPCI_SUCCESS_32);
+	EXPECT_EQ(ret.arg1, current_version);
 }
 
 /**