Move non-trivial SPCI helper functions to a source file.
Also stop manually copying hf_call.c to kernel module, instead
copying as part of build.
Change-Id: I646ac994b5dc3de0bb4ce501323ea36a8a6fe009
diff --git a/driver/linux b/driver/linux
index 06046ea..4cc539b 160000
--- a/driver/linux
+++ b/driver/linux
@@ -1 +1 @@
-Subproject commit 06046eac25b06e5c2a81672acffb64b81ea1eca1
+Subproject commit 4cc539b162643dc512fe997d748c54cfa0296d6f
diff --git a/inc/vmapi/hf/spci.h b/inc/vmapi/hf/spci.h
index b00fb46..30feb0e 100644
--- a/inc/vmapi/hf/spci.h
+++ b/inc/vmapi/hf/spci.h
@@ -18,14 +18,6 @@
#include "hf/types.h"
-/*
- * Copied from hf/arch/std.h because we can't include Hafnium internal headers
- * here.
- */
-#ifndef align_up
-#define align_up(v, a) (((uintptr_t)(v) + (a - 1)) & ~(a - 1))
-#endif
-
/* clang-format off */
#define SPCI_LOW_32_ID 0x84000060
@@ -310,8 +302,6 @@
struct spci_memory_region_attributes attributes[];
};
-/* TODO: Move all the functions below this line to a support library. */
-
/**
* Gets the constituent array for an `spci_memory_region`.
*/
@@ -323,20 +313,7 @@
memory_region->constituent_offset);
}
-/**
- * Helper method to fill in the information about the architected message.
- */
-static inline void spci_architected_message_init(void *message,
- enum spci_memory_share type)
-{
- /* Fill the architected header. */
- struct spci_architected_message_header *architected_header =
- (struct spci_architected_message_header *)message;
- architected_header->type = type;
- architected_header->reserved[0] = 0;
- architected_header->reserved[1] = 0;
- architected_header->reserved[2] = 0;
-}
+void spci_architected_message_init(void *message, enum spci_memory_share type);
/** Gets the spci_memory_region within an architected message. */
static inline struct spci_memory_region *spci_get_memory_region(void *message)
@@ -346,92 +323,21 @@
return (struct spci_memory_region *)architected_header->payload;
}
-/**
- * Initialises the given `spci_memory_region` and copies the constituent
- * information to it. Returns the length in bytes occupied by the data copied to
- * `memory_region` (attributes, constituents and memory region header size).
- */
-static inline uint32_t spci_memory_region_init(
+uint32_t spci_memory_region_init(
struct spci_memory_region *memory_region, spci_vm_id_t receiver,
const struct spci_memory_region_constituent constituents[],
uint32_t constituent_count, uint32_t tag,
enum spci_memory_access access, enum spci_memory_type type,
enum spci_memory_cacheability cacheability,
- enum spci_memory_shareability shareability)
-{
- uint32_t constituents_length =
- constituent_count *
- sizeof(struct spci_memory_region_constituent);
- uint32_t index;
- struct spci_memory_region_constituent *region_constituents;
- uint16_t attributes = 0;
+ enum spci_memory_shareability shareability);
- /* Set memory region's page attributes. */
- spci_set_memory_access_attr(&attributes, access);
- spci_set_memory_type_attr(&attributes, type);
- spci_set_memory_cacheability_attr(&attributes, cacheability);
- spci_set_memory_shareability_attr(&attributes, shareability);
-
- memory_region->tag = tag;
- memory_region->flags = 0;
- memory_region->page_count = 0;
- memory_region->constituent_count = constituent_count;
- memory_region->attribute_count = 1;
- memory_region->attributes[0].receiver = receiver;
- memory_region->attributes[0].memory_attributes = attributes;
-
- /*
- * Constituent offset must be aligned to a 64-bit boundary so that
- * 64-bit addresses can be copied without alignment faults.
- */
- memory_region->constituent_offset = align_up(
- sizeof(struct spci_memory_region) +
- memory_region->attribute_count *
- sizeof(struct spci_memory_region_attributes),
- 8);
- region_constituents =
- spci_memory_region_get_constituents(memory_region);
-
- for (index = 0; index < constituent_count; index++) {
- region_constituents[index] = constituents[index];
- region_constituents[index].reserved = 0;
- memory_region->page_count += constituents[index].page_count;
- }
-
- /*
- * TODO: Add assert ensuring that the specified message
- * length is not greater than SPCI_MSG_PAYLOAD_MAX.
- */
-
- return memory_region->constituent_offset + constituents_length;
-}
-
-/**
- * Constructs an 'architected message' for SPCI memory sharing of the given
- * type.
- */
-static inline uint32_t spci_memory_init(
+uint32_t spci_memory_init(
void *message, enum spci_memory_share share_type, spci_vm_id_t receiver,
struct spci_memory_region_constituent *region_constituents,
uint32_t constituent_count, uint32_t tag,
enum spci_memory_access access, enum spci_memory_type type,
enum spci_memory_cacheability cacheability,
- enum spci_memory_shareability shareability)
-{
- uint32_t message_length =
- sizeof(struct spci_architected_message_header);
- struct spci_memory_region *memory_region =
- spci_get_memory_region(message);
-
- /* Fill in the details on the common message header. */
- spci_architected_message_init(message, share_type);
-
- /* Fill in memory region. */
- message_length += spci_memory_region_init(
- memory_region, receiver, region_constituents, constituent_count,
- tag, access, type, cacheability, shareability);
- return message_length;
-}
+ enum spci_memory_shareability shareability);
/** Constructs an SPCI donate memory region message. */
static inline uint32_t spci_memory_donate_init(
diff --git a/src/arch/aarch64/hftest/BUILD.gn b/src/arch/aarch64/hftest/BUILD.gn
index 044c874..a06ef24 100644
--- a/src/arch/aarch64/hftest/BUILD.gn
+++ b/src/arch/aarch64/hftest/BUILD.gn
@@ -21,13 +21,6 @@
]
}
-# Make a call to the hypervisor from a VM.
-source_set("hf_call") {
- sources = [
- "hf_call.c",
- ]
-}
-
# Shutdown the system or exit emulation, start/stop CPUs.
source_set("power_mgmt") {
testonly = true
@@ -85,7 +78,7 @@
]
deps = [
- "//src/arch/aarch64/hftest:hf_call",
+ "//vmlib/aarch64:call",
]
}
diff --git a/test/hftest/BUILD.gn b/test/hftest/BUILD.gn
index e23e817..81525a2 100644
--- a/test/hftest/BUILD.gn
+++ b/test/hftest/BUILD.gn
@@ -26,7 +26,7 @@
deps = [
":hftest_standalone",
- "//src/arch/${plat_arch}/hftest:hf_call",
+ "//vmlib/${plat_arch}:call",
]
}
@@ -50,8 +50,8 @@
"//src:std",
"//src/arch/${plat_arch}:entry",
"//src/arch/${plat_arch}/hftest:entry",
- "//src/arch/${plat_arch}/hftest:hf_call",
"//src/arch/${plat_arch}/hftest:power_mgmt",
+ "//vmlib/${plat_arch}:call",
]
}
diff --git a/test/vmapi/primary_with_secondaries/BUILD.gn b/test/vmapi/primary_with_secondaries/BUILD.gn
index 801d8b6..54501f7 100644
--- a/test/vmapi/primary_with_secondaries/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/BUILD.gn
@@ -42,6 +42,7 @@
":util",
"//src/arch/aarch64/hftest:registers",
"//test/hftest:hftest_primary_vm",
+ "//vmlib",
]
}
diff --git a/test/vmapi/primary_with_secondaries/services/BUILD.gn b/test/vmapi/primary_with_secondaries/services/BUILD.gn
index 732a655..dc395c0 100644
--- a/test/vmapi/primary_with_secondaries/services/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/services/BUILD.gn
@@ -95,6 +95,7 @@
]
deps = [
"//test/vmapi/primary_with_secondaries:util",
+ "//vmlib",
]
sources = [
diff --git a/vmlib/BUILD.gn b/vmlib/BUILD.gn
new file mode 100644
index 0000000..9ba8c3d
--- /dev/null
+++ b/vmlib/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/toolchain/platform.gni")
+
+source_set("vmlib") {
+ sources = [
+ "spci.c",
+ ]
+}
diff --git a/vmlib/aarch64/BUILD.gn b/vmlib/aarch64/BUILD.gn
new file mode 100644
index 0000000..4ddd659
--- /dev/null
+++ b/vmlib/aarch64/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2019 The Hafnium Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build/toolchain/platform.gni")
+
+source_set("call") {
+ sources = [
+ "call.c",
+ ]
+}
diff --git a/src/arch/aarch64/hftest/hf_call.c b/vmlib/aarch64/call.c
similarity index 99%
rename from src/arch/aarch64/hftest/hf_call.c
rename to vmlib/aarch64/call.c
index a48a797..0c1a078 100644
--- a/src/arch/aarch64/hftest/hf_call.c
+++ b/vmlib/aarch64/call.c
@@ -15,6 +15,7 @@
*/
#include "hf/call.h"
+
#include "hf/spci.h"
#include "hf/types.h"
diff --git a/vmlib/spci.c b/vmlib/spci.c
new file mode 100644
index 0000000..93fe88d
--- /dev/null
+++ b/vmlib/spci.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2019 The Hafnium Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "hf/spci.h"
+
+#include "hf/types.h"
+
+/*
+ * Copied from hf/arch/std.h because we can't include Hafnium internal headers
+ * here.
+ */
+#ifndef align_up
+#define align_up(v, a) (((uintptr_t)(v) + ((a)-1)) & ~((a)-1))
+#endif
+
+/**
+ * Helper method to fill in the information about the architected message.
+ */
+void spci_architected_message_init(void *message, enum spci_memory_share type)
+{
+ /* Fill the architected header. */
+ struct spci_architected_message_header *architected_header =
+ (struct spci_architected_message_header *)message;
+ architected_header->type = type;
+ architected_header->reserved[0] = 0;
+ architected_header->reserved[1] = 0;
+ architected_header->reserved[2] = 0;
+}
+
+/**
+ * Initialises the given `spci_memory_region` and copies the constituent
+ * information to it. Returns the length in bytes occupied by the data copied to
+ * `memory_region` (attributes, constituents and memory region header size).
+ */
+uint32_t spci_memory_region_init(
+ struct spci_memory_region *memory_region, spci_vm_id_t receiver,
+ const struct spci_memory_region_constituent constituents[],
+ uint32_t constituent_count, uint32_t tag,
+ enum spci_memory_access access, enum spci_memory_type type,
+ enum spci_memory_cacheability cacheability,
+ enum spci_memory_shareability shareability)
+{
+ uint32_t constituents_length =
+ constituent_count *
+ sizeof(struct spci_memory_region_constituent);
+ uint32_t index;
+ struct spci_memory_region_constituent *region_constituents;
+ uint16_t attributes = 0;
+
+ /* Set memory region's page attributes. */
+ spci_set_memory_access_attr(&attributes, access);
+ spci_set_memory_type_attr(&attributes, type);
+ spci_set_memory_cacheability_attr(&attributes, cacheability);
+ spci_set_memory_shareability_attr(&attributes, shareability);
+
+ memory_region->tag = tag;
+ memory_region->flags = 0;
+ memory_region->page_count = 0;
+ memory_region->constituent_count = constituent_count;
+ memory_region->attribute_count = 1;
+ memory_region->attributes[0].receiver = receiver;
+ memory_region->attributes[0].memory_attributes = attributes;
+
+ /*
+ * Constituent offset must be aligned to a 64-bit boundary so that
+ * 64-bit addresses can be copied without alignment faults.
+ */
+ memory_region->constituent_offset = align_up(
+ sizeof(struct spci_memory_region) +
+ memory_region->attribute_count *
+ sizeof(struct spci_memory_region_attributes),
+ 8);
+ region_constituents =
+ spci_memory_region_get_constituents(memory_region);
+
+ for (index = 0; index < constituent_count; index++) {
+ region_constituents[index] = constituents[index];
+ region_constituents[index].reserved = 0;
+ memory_region->page_count += constituents[index].page_count;
+ }
+
+ /*
+ * TODO: Add assert ensuring that the specified message
+ * length is not greater than SPCI_MSG_PAYLOAD_MAX.
+ */
+
+ return memory_region->constituent_offset + constituents_length;
+}
+
+/**
+ * Constructs an 'architected message' for SPCI memory sharing of the given
+ * type.
+ */
+uint32_t spci_memory_init(
+ void *message, enum spci_memory_share share_type, spci_vm_id_t receiver,
+ struct spci_memory_region_constituent *region_constituents,
+ uint32_t constituent_count, uint32_t tag,
+ enum spci_memory_access access, enum spci_memory_type type,
+ enum spci_memory_cacheability cacheability,
+ enum spci_memory_shareability shareability)
+{
+ uint32_t message_length =
+ sizeof(struct spci_architected_message_header);
+ struct spci_memory_region *memory_region =
+ spci_get_memory_region(message);
+
+ /* Fill in the details on the common message header. */
+ spci_architected_message_init(message, share_type);
+
+ /* Fill in memory region. */
+ message_length += spci_memory_region_init(
+ memory_region, receiver, region_constituents, constituent_count,
+ tag, access, type, cacheability, shareability);
+ return message_length;
+}