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. */