fix: remove redundant CPU_ON event subscription for VMs
In the next patch, we implement support for bootstrapping all pinned
execution context of SPs on secondary CPUs upon receiving CPU_ON power
management event. This makes the support for CPU_ON subscription,
through partition manifest, redundant.
Also, SPMC falls back to entrypoint used for primary execution context
if an MP SP fails to register entrypoint for secondary execution
contexts using FFA_SECONDARY_EP_REGISTER interface.
Change-Id: I15bd8ab20469b4bfb7159f2ad60af55e57355dd8
Signed-off-by: Madhukar Pappireddy <madhukar.pappireddy@arm.com>
diff --git a/src/arch/aarch64/plat/psci/spmc.c b/src/arch/aarch64/plat/psci/spmc.c
index 632596e..c2b8653 100644
--- a/src/arch/aarch64/plat/psci/spmc.c
+++ b/src/arch/aarch64/plat/psci/spmc.c
@@ -77,8 +77,7 @@
vcpu_locked = vcpu_lock(vcpu);
- if (vcpu->rt_model != RTM_SP_INIT &&
- vm_power_management_cpu_on_requested(vm) == false) {
+ if (vcpu->rt_model != RTM_SP_INIT) {
other_world_vm = vm_find(HF_OTHER_WORLD_ID);
CHECK(other_world_vm != NULL);
other_world_vcpu = vm_get_vcpu(other_world_vm, cpu_index(c));
diff --git a/src/load.c b/src/load.c
index ea38f25..b2dc996 100644
--- a/src/load.c
+++ b/src/load.c
@@ -667,7 +667,7 @@
struct vm_locked vm_locked;
struct vcpu_locked vcpu_locked;
struct vcpu *vcpu;
- ipaddr_t secondary_entry;
+ ipaddr_t partition_primary_ep;
bool ret;
paddr_t fdt_addr;
bool has_fdt;
@@ -752,7 +752,7 @@
}
if (!vm_identity_map(vm_locked, mem_begin, mem_end, map_mode, ppool,
- &secondary_entry)) {
+ &partition_primary_ep)) {
dlog_error("Unable to initialise memory.\n");
ret = false;
goto out;
@@ -765,9 +765,15 @@
ret = false;
goto out;
}
+ partition_primary_ep = ipa_add(
+ partition_primary_ep, manifest_vm->partition.ep_offset);
- secondary_entry = ipa_add(secondary_entry,
- manifest_vm->partition.ep_offset);
+ /*
+ * If MP endpoints dont specify the entrypoint for secondary
+ * execution contexts, FF-A spec advises SPMC to reuse the
+ * entrypoint computed for primary execution context.
+ */
+ vm->secondary_ep = partition_primary_ep;
}
/*
@@ -810,16 +816,16 @@
vcpu_locked = vcpu_lock(vcpu);
if (has_fdt) {
- vcpu_secondary_reset_and_start(vcpu_locked, secondary_entry,
- pa_addr(fdt_addr));
+ vcpu_secondary_reset_and_start(
+ vcpu_locked, partition_primary_ep, pa_addr(fdt_addr));
} else {
/*
* Without an FDT, secondary VMs expect the memory size to be
* passed in register x0, which is what
* vcpu_secondary_reset_and_start does in this case.
*/
- vcpu_secondary_reset_and_start(vcpu_locked, secondary_entry,
- mem_size);
+ vcpu_secondary_reset_and_start(vcpu_locked,
+ partition_primary_ep, mem_size);
}
vcpu_unlock(&vcpu_locked);
diff --git a/src/manifest.c b/src/manifest.c
index f4edaaf..a9b61e4 100644
--- a/src/manifest.c
+++ b/src/manifest.c
@@ -1445,11 +1445,9 @@
return MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID;
}
- TRY(read_optional_uint32(
- &root, "power-management-messages",
- MANIFEST_POWER_MANAGEMENT_CPU_OFF_SUPPORTED |
- MANIFEST_POWER_MANAGEMENT_CPU_ON_SUPPORTED,
- &vm->partition.power_management));
+ TRY(read_optional_uint32(&root, "power-management-messages",
+ MANIFEST_POWER_MANAGEMENT_CPU_OFF_SUPPORTED,
+ &vm->partition.power_management));
vm->partition.power_management &= MANIFEST_POWER_MANAGEMENT_ALL_MASK;
if (vm->partition.execution_ctx_count == 1 ||
vm->partition.run_time_el == S_EL0 ||
diff --git a/src/manifest_test.cc b/src/manifest_test.cc
index 8bcef30..4a78f59 100644
--- a/src/manifest_test.cc
+++ b/src/manifest_test.cc
@@ -1228,7 +1228,7 @@
struct manifest_vm *vm;
struct_manifest *m;
- /* S-EL1 partition power management field can set bit 0. */
+ /* S-EL1 partition power management field can only set bit 0. */
/* clang-format off */
std::vector<char> dtb = ManifestDtBuilder()
.Compatible({ "arm,ffa-manifest-1.0" })
@@ -1239,50 +1239,12 @@
.Property("execution-state", "<0>")
.Property("entrypoint-offset", "<0x00002000>")
.Property("messaging-method", "<1>")
- .Property("power-management-messages", "<1>")
- .Build();
- /* clang-format on */
- ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
- vm = &m->vm[0];
- ASSERT_EQ(vm->partition.power_management, 1);
- manifest_dealloc();
-
- /* S-EL1 partition power management field can set bit 3. */
- /* clang-format off */
- dtb = ManifestDtBuilder()
- .Compatible({ "arm,ffa-manifest-1.0" })
- .Property("ffa-version", "<0x10001>")
- .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
- .Property("execution-ctx-count", "<8>")
- .Property("exception-level", "<2>")
- .Property("execution-state", "<0>")
- .Property("entrypoint-offset", "<0x00002000>")
- .Property("messaging-method", "<1>")
- .Property("power-management-messages", "<8>")
- .Build();
- /* clang-format on */
- ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
- vm = &m->vm[0];
- ASSERT_EQ(vm->partition.power_management, 8);
- manifest_dealloc();
-
- /* S-EL1 partition power management field can only set bits 0 and 3. */
- /* clang-format off */
- dtb = ManifestDtBuilder()
- .Compatible({ "arm,ffa-manifest-1.0" })
- .Property("ffa-version", "<0x10001>")
- .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
- .Property("execution-ctx-count", "<8>")
- .Property("exception-level", "<2>")
- .Property("execution-state", "<0>")
- .Property("entrypoint-offset", "<0x00002000>")
- .Property("messaging-method", "<1>")
.Property("power-management-messages", "<0xf>")
.Build();
/* clang-format on */
ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
vm = &m->vm[0];
- ASSERT_EQ(vm->partition.power_management, 9);
+ ASSERT_EQ(vm->partition.power_management, 1);
manifest_dealloc();
/* S-EL0 partition power management field is forced to 0. */