refactor: boot order list to use list.h
The boot order list is built using the list.h helper.
The structure list_entry uses the same type to point
to the nodes of the list. The root of the list doesn't
have any data. Any other node shall be part of a vCPU
structure whose data is returned via CONTAINER_OF
structure.
The list implementation is circular. As such, root is
also the end of the list. The last node points to the
beginning(i.e. vcpu.next_boot.next is root entry).
Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: Idbfaa293c74e71b989133d5828803c958855d25a
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index 4b61dfe..910e7fb 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -2115,7 +2115,8 @@
* Pick next vCPU to be booted. Once all SPs have booted
* (next_boot is NULL), then return execution to NWd.
*/
- vcpu_next = current->next_boot;
+ vcpu_next = vcpu_get_next_boot(current);
+
if (vcpu_next == NULL) {
dlog_notice("Finished initializing all VMs.\n");
spmc_booted = true;
diff --git a/src/arch/aarch64/plat/psci/spmc.c b/src/arch/aarch64/plat/psci/spmc.c
index a8a2256..7f9fb01 100644
--- a/src/arch/aarch64/plat/psci/spmc.c
+++ b/src/arch/aarch64/plat/psci/spmc.c
@@ -62,11 +62,14 @@
struct vcpu_locked vcpu_locked;
struct vcpu_locked other_world_vcpu_locked;
struct vcpu *vcpu = vcpu_get_boot_vcpu();
- struct vm *vm = vcpu->vm;
+ struct vm *vm;
struct vm *other_world_vm;
struct vcpu *other_world_vcpu;
struct two_vcpu_locked vcpus_locked;
+ assert(vcpu != NULL);
+
+ vm = vcpu->vm;
cpu_on(c);
arch_cpu_init(c);
diff --git a/src/vcpu.c b/src/vcpu.c
index 9130ff1..b54fb90 100644
--- a/src/vcpu.c
+++ b/src/vcpu.c
@@ -15,7 +15,7 @@
#include "hf/std.h"
#include "hf/vm.h"
-static struct vcpu *boot_vcpu;
+static struct list_entry boot_list = LIST_INIT(boot_list);
/** GP register to be used to pass the current vCPU ID, at core bring up. */
#define PHYS_CORE_IDX_GP_REG 4
@@ -69,7 +69,7 @@
vcpu->direct_request_origin.is_ffa_req2 = false;
vcpu->direct_request_origin.vm_id = HF_INVALID_VM_ID;
vcpu->rt_model = RTM_SP_INIT;
- vcpu->next_boot = NULL;
+ list_init(&vcpu->boot_list_node);
}
/**
@@ -221,11 +221,34 @@
}
/**
+ * The 'boot_list' is used as the start and end of the list.
+ * Start: the nodes it points to is the first vCPU to boot.
+ * End: the last node's next points to the entry.
+ */
+static bool vcpu_is_boot_list_end(struct vcpu *vcpu)
+{
+ return vcpu->boot_list_node.next == &boot_list;
+}
+
+/**
* Gets the first partition to boot, according to Boot Protocol from FFA spec.
*/
struct vcpu *vcpu_get_boot_vcpu(void)
{
- return boot_vcpu;
+ assert(!list_empty(&boot_list));
+
+ return CONTAINER_OF(boot_list.next, struct vcpu, boot_list_node);
+}
+
+/**
+ * Returns the next element in the boot order list, if there is one.
+ */
+struct vcpu *vcpu_get_next_boot(struct vcpu *vcpu)
+{
+ return vcpu_is_boot_list_end(vcpu)
+ ? NULL
+ : CONTAINER_OF(vcpu->boot_list_node.next, struct vcpu,
+ boot_list_node);
}
/**
@@ -235,28 +258,31 @@
void vcpu_update_boot(struct vcpu *vcpu)
{
struct vcpu *current = NULL;
- struct vcpu *previous = NULL;
- if (boot_vcpu == NULL) {
- boot_vcpu = vcpu;
+ if (list_empty(&boot_list)) {
+ list_prepend(&boot_list, &vcpu->boot_list_node);
return;
}
- current = boot_vcpu;
+ /*
+ * When getting to this point the first insertion should have
+ * been done.
+ */
+ current = vcpu_get_boot_vcpu();
+ assert(current != NULL);
- while (current != NULL &&
+ /*
+ * Iterate until the position is found according to boot order, or
+ * until we reach end of the list.
+ */
+ while (!vcpu_is_boot_list_end(current) &&
current->vm->boot_order <= vcpu->vm->boot_order) {
- previous = current;
- current = current->next_boot;
+ current = vcpu_get_next_boot(current);
}
- if (previous != NULL) {
- previous->next_boot = vcpu;
- } else {
- boot_vcpu = vcpu;
- }
-
- vcpu->next_boot = current;
+ current->vm->boot_order > vcpu->vm->boot_order
+ ? list_prepend(¤t->boot_list_node, &vcpu->boot_list_node)
+ : list_append(¤t->boot_list_node, &vcpu->boot_list_node);
}
void vcpu_interrupt_clear_decrement(struct vcpu_locked vcpu_locked,
diff --git a/src/vm_test.cc b/src/vm_test.cc
index 40b0e60..b82aaf6 100644
--- a/src/vm_test.cc
+++ b/src/vm_test.cc
@@ -10,6 +10,7 @@
extern "C" {
#include "hf/check.h"
+#include "hf/list.h"
#include "hf/mpool.h"
#include "hf/vm.h"
}
@@ -96,8 +97,6 @@
struct_vcpu *vcpu;
std::list<struct_vm *> expected_final_order;
- EXPECT_TRUE(vcpu_get_boot_vcpu() == NULL);
-
/*
* Insertion when no call to "vcpu_update_boot" has been made yet.
* The "boot_list" is expected to be empty.
@@ -156,7 +155,7 @@
it != expected_final_order.end(); it++) {
EXPECT_TRUE(vcpu != NULL);
EXPECT_EQ((*it)->id, vcpu->vm->id);
- vcpu = vcpu->next_boot;
+ vcpu = vcpu_get_next_boot(vcpu);
}
}