Update SPCI_VERSION implementation to match latest spec.

This also updates the version number from 0.9 to 1.0.

Bug: 132420445
Change-Id: I991ea9f71634935c21a590f9309dd66ac910eff5
diff --git a/inc/hf/api.h b/inc/hf/api.h
index 9de3928..ebc533b 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -55,7 +55,7 @@
 				    uint32_t page_count, struct vcpu *current,
 				    struct vcpu **next);
 void api_yield(struct vcpu *current, struct vcpu **next);
-struct spci_value api_spci_version(void);
+struct spci_value api_spci_version(uint32_t requested_version);
 struct spci_value api_spci_id_get(const struct vcpu *current);
 struct spci_value api_spci_features(uint32_t function_id);
 struct spci_value api_spci_run(spci_vm_id_t vm_id, spci_vcpu_index_t vcpu_idx,
diff --git a/inc/hf/spci_internal.h b/inc/hf/spci_internal.h
index fe21e1f..1c2ccff 100644
--- a/inc/hf/spci_internal.h
+++ b/inc/hf/spci_internal.h
@@ -20,10 +20,11 @@
 
 #include "vmapi/hf/spci.h"
 
-#define SPCI_VERSION_MAJOR 0x0
-#define SPCI_VERSION_MINOR 0x9
+#define SPCI_VERSION_MAJOR 0x1
+#define SPCI_VERSION_MINOR 0x0
 
 #define SPCI_VERSION_MAJOR_OFFSET 16
+#define SPCI_VERSION_RESERVED_BIT UINT32_C(1U << 31)
 
 static inline struct spci_value spci_error(uint64_t error_code)
 {
diff --git a/inc/vmapi/hf/call.h b/inc/vmapi/hf/call.h
index 5642683..d4119d6 100644
--- a/inc/vmapi/hf/call.h
+++ b/inc/vmapi/hf/call.h
@@ -319,9 +319,11 @@
 }
 
 /** Obtains the Hafnium's version of the implemented SPCI specification. */
-static inline struct spci_value spci_version(void)
+static inline int32_t spci_version(uint32_t requested_version)
 {
-	return spci_call((struct spci_value){.func = SPCI_VERSION_32});
+	return spci_call((struct spci_value){.func = SPCI_VERSION_32,
+					     .arg1 = requested_version})
+		.func;
 }
 
 /**
diff --git a/src/api.c b/src/api.c
index 8f8272e..988e5f6 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1384,22 +1384,24 @@
 }
 
 /** Returns the version of the implemented SPCI specification. */
-struct spci_value api_spci_version(void)
+struct spci_value api_spci_version(uint32_t requested_version)
 {
 	/*
 	 * Ensure that both major and minor revision representation occupies at
 	 * most 15 bits.
 	 */
 	static_assert(0x8000 > SPCI_VERSION_MAJOR,
-		      "Major revision representation take more than 15 bits.");
+		      "Major revision representation takes more than 15 bits.");
 	static_assert(0x10000 > SPCI_VERSION_MINOR,
-		      "Minor revision representation take more than 16 bits.");
+		      "Minor revision representation takes more than 16 bits.");
+	if (requested_version & SPCI_VERSION_RESERVED_BIT) {
+		/* Invalid encoding, return an error. */
+		return (struct spci_value){.func = SPCI_NOT_SUPPORTED};
+	}
 
-	struct spci_value ret = {
-		.func = SPCI_SUCCESS_32,
-		.arg2 = (SPCI_VERSION_MAJOR << SPCI_VERSION_MAJOR_OFFSET) |
+	return (struct spci_value){
+		.func = (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/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 4a4f035..924d024 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -323,7 +323,7 @@
 	 */
 	switch (func) {
 	case SPCI_VERSION_32:
-		*args = api_spci_version();
+		*args = api_spci_version(args->arg1);
 		return true;
 	case SPCI_ID_GET_32:
 		*args = api_spci_id_get(current());
diff --git a/test/vmapi/primary_only/primary_only.c b/test/vmapi/primary_only/primary_only.c
index 75df306..e5cf198 100644
--- a/test/vmapi/primary_only/primary_only.c
+++ b/test/vmapi/primary_only/primary_only.c
@@ -201,15 +201,26 @@
 /** Ensures that the Hafnium SPCI version is reported as expected. */
 TEST(spci, spci_version)
 {
-	const int32_t major_revision = 0;
+	const int32_t major_revision = 1;
 	const int32_t major_revision_offset = 16;
-	const int32_t minor_revision = 9;
+	const int32_t minor_revision = 0;
 	const int32_t current_version =
 		(major_revision << major_revision_offset) | minor_revision;
 
-	struct spci_value ret = spci_version();
-	EXPECT_EQ(ret.func, SPCI_SUCCESS_32);
-	EXPECT_EQ(ret.arg2, current_version);
+	EXPECT_EQ(spci_version(current_version), current_version);
+	EXPECT_EQ(spci_version(0x0), current_version);
+	EXPECT_EQ(spci_version(0x1), current_version);
+	EXPECT_EQ(spci_version(0x10003), current_version);
+	EXPECT_EQ(spci_version(0xffff), current_version);
+	EXPECT_EQ(spci_version(0xfffffff), current_version);
+}
+
+/** Ensures that an invalid call to SPCI_VERSION gets an error back. */
+TEST(spci, spci_version_invalid)
+{
+	int32_t ret = spci_version(0x80000000);
+
+	EXPECT_EQ(ret, SPCI_NOT_SUPPORTED);
 }
 
 /** Ensures that SPCI_FEATURES is reporting the expected interfaces. */