feat: remove waiter list
FF-A v1.1 deprecate FFA_MSG_SEND ABI and the notification feature in
case of busy receiver.
Change-Id: I30ad97930f872ac097d398085621d1e3e2bee15f
Signed-off-by: Federico Recanati <federico.recanati@arm.com>
diff --git a/inc/hf/api.h b/inc/hf/api.h
index f17f1fb..929fe52 100644
--- a/inc/hf/api.h
+++ b/inc/hf/api.h
@@ -41,8 +41,7 @@
struct ffa_value api_ffa_msg_send(ffa_vm_id_t sender_vm_id,
ffa_vm_id_t receiver_vm_id, uint32_t size,
- uint32_t attributes, struct vcpu *current,
- struct vcpu **next);
+ struct vcpu *current, struct vcpu **next);
struct ffa_value api_ffa_msg_send2(ffa_vm_id_t sender_vm_id, uint32_t flags,
struct vcpu *current);
struct ffa_value api_ffa_msg_recv(bool block, struct vcpu *current,
diff --git a/inc/vmapi/hf/ffa.h b/inc/vmapi/hf/ffa.h
index 7fe1f50..8d6d59c 100644
--- a/inc/vmapi/hf/ffa.h
+++ b/inc/vmapi/hf/ffa.h
@@ -367,11 +367,6 @@
return args.arg3;
}
-static inline uint32_t ffa_msg_send_attributes(struct ffa_value args)
-{
- return args.arg4;
-}
-
static inline uint32_t ffa_msg_send2_flags(struct ffa_value args)
{
return args.arg2;
diff --git a/src/api.c b/src/api.c
index b4055ed..1e1f781 100644
--- a/src/api.c
+++ b/src/api.c
@@ -187,32 +187,12 @@
}
/**
- * Checks whether the given `to` VM's mailbox is currently busy, and optionally
- * registers the `from` VM to be notified when it becomes available.
+ * Checks whether the given `to` VM's mailbox is currently busy.
*/
-static bool msg_receiver_busy(struct vm_locked to, struct vm *from, bool notify)
+static bool msg_receiver_busy(struct vm_locked to)
{
- if (to.vm->mailbox.state != MAILBOX_STATE_EMPTY ||
- to.vm->mailbox.recv == NULL) {
- /*
- * Fail if the receiver isn't currently ready to receive data,
- * setting up for notification if requested.
- */
- if (notify) {
- struct wait_entry *entry =
- vm_get_wait_entry(from, to.vm->id);
-
- /* Append waiter only if it's not there yet. */
- if (list_empty(&entry->wait_links)) {
- list_append(&to.vm->mailbox.waiter_list,
- &entry->wait_links);
- }
- }
-
- return true;
- }
-
- return false;
+ return to.vm->mailbox.state != MAILBOX_STATE_EMPTY ||
+ to.vm->mailbox.recv == NULL;
}
/**
@@ -369,7 +349,7 @@
uint32_t buffer_size;
struct ffa_value ret;
- if (msg_receiver_busy(vm_locked, NULL, false)) {
+ if (msg_receiver_busy(vm_locked)) {
/*
* Can't retrieve memory information if the mailbox is not
* available.
@@ -1044,6 +1024,8 @@
{
struct vm *vm = locked_vm.vm;
+ CHECK(list_empty(&vm->mailbox.waiter_list));
+
if (list_empty(&vm->mailbox.waiter_list)) {
/* No waiters, nothing else to do. */
return (struct ffa_value){.func = FFA_SUCCESS_32};
@@ -1538,8 +1520,7 @@
*/
struct ffa_value api_ffa_msg_send(ffa_vm_id_t sender_vm_id,
ffa_vm_id_t receiver_vm_id, uint32_t size,
- uint32_t attributes, struct vcpu *current,
- struct vcpu **next)
+ struct vcpu *current, struct vcpu **next)
{
struct vm *from = current->vm;
struct vm *to;
@@ -1548,8 +1529,6 @@
struct ffa_value ret;
struct vcpu_locked current_locked;
bool is_direct_request_ongoing;
- bool notify =
- (attributes & FFA_MSG_SEND_NOTIFY_MASK) == FFA_MSG_SEND_NOTIFY;
/* Ensure sender VM ID corresponds to the current VM. */
if (sender_vm_id != from->id) {
@@ -1601,7 +1580,7 @@
to_locked = vm_lock(to);
- if (msg_receiver_busy(to_locked, from, notify)) {
+ if (msg_receiver_busy(to_locked)) {
ret = ffa_error(FFA_BUSY);
goto out;
}
@@ -2893,7 +2872,7 @@
*/
struct two_vm_locked vm_to_from_lock = vm_lock_both(to, from);
- if (msg_receiver_busy(vm_to_from_lock.vm1, from, false)) {
+ if (msg_receiver_busy(vm_to_from_lock.vm1)) {
ret = ffa_error(FFA_BUSY);
goto out_unlock;
}
@@ -2981,7 +2960,7 @@
*/
memcpy_s(retrieve_request, message_buffer_size, to_msg, length);
- if (msg_receiver_busy(to_locked, NULL, false)) {
+ if (msg_receiver_busy(to_locked)) {
/*
* Can't retrieve memory information if the mailbox is not
* available.
@@ -3102,7 +3081,7 @@
to_locked = vm_lock(to);
- if (msg_receiver_busy(to_locked, NULL, false)) {
+ if (msg_receiver_busy(to_locked)) {
/*
* Can't retrieve memory information if the mailbox is not
* available.
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 0ee37d6..0d46b66 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -515,9 +515,8 @@
return true;
case FFA_MSG_SEND_32:
*args = api_ffa_msg_send(ffa_sender(*args), ffa_receiver(*args),
- ffa_msg_send_size(*args),
- ffa_msg_send_attributes(*args),
- current, next);
+ ffa_msg_send_size(*args), current,
+ next);
return true;
case FFA_MSG_SEND2_32:
*args = api_ffa_msg_send2(ffa_sender(*args),
diff --git a/test/vmapi/el0_partitions/BUILD.gn b/test/vmapi/el0_partitions/BUILD.gn
index eee567e..1210b22 100644
--- a/test/vmapi/el0_partitions/BUILD.gn
+++ b/test/vmapi/el0_partitions/BUILD.gn
@@ -44,7 +44,6 @@
"//test/vmapi/primary_with_secondaries/mailbox_common.c",
"boot.c",
"interrupts.c",
- "mailbox.c",
]
deps = [
diff --git a/test/vmapi/el0_partitions/mailbox.c b/test/vmapi/el0_partitions/mailbox.c
deleted file mode 100644
index 1285014..0000000
--- a/test/vmapi/el0_partitions/mailbox.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2021 The Hafnium Authors.
- *
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/BSD-3-Clause.
- */
-
-#include <stdint.h>
-
-#include "hf/ffa.h"
-#include "hf/std.h"
-
-#include "vmapi/hf/call.h"
-
-#include "primary_with_secondary.h"
-#include "test/hftest.h"
-#include "test/vmapi/ffa.h"
-
-/**
- * Causes secondary VM to send two messages to primary VM. The second message
- * will reach the mailbox while it's not writable. Checks that notifications are
- * properly delivered when mailbox is cleared.
- */
-TEST(mailbox, primary_to_secondary)
-{
- char message[] = "not ready echo";
- struct ffa_value run_res;
- struct mailbox_buffers mb = set_up_mailbox();
-
- SERVICE_SELECT(SERVICE_VM1, "echo_with_notification", mb.send);
-
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Send a message to echo service, and get response back. */
- memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
- EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
-
- /* Let secondary VM continue running so that it will wait again. */
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Without clearing our mailbox, send message again. */
- reverse(message, strnlen_s(message, sizeof(message)));
- memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
-
- /* Message should be dropped since the mailbox was not cleared. */
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_YIELD_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Clear the mailbox. We expect to be told there are pending waiters. */
- EXPECT_EQ(ffa_rx_release().func, FFA_RX_RELEASE_32);
-
- /* Retrieve a single waiter. */
- EXPECT_EQ(hf_mailbox_waiter_get(HF_PRIMARY_VM_ID), SERVICE_VM1);
- EXPECT_EQ(hf_mailbox_waiter_get(HF_PRIMARY_VM_ID), -1);
-
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
- EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
- EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
-}
diff --git a/test/vmapi/primary_with_secondaries/BUILD.gn b/test/vmapi/primary_with_secondaries/BUILD.gn
index 094762a..a005bd0 100644
--- a/test/vmapi/primary_with_secondaries/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/BUILD.gn
@@ -85,7 +85,6 @@
"floating_point.c",
"indirect_messaging.c",
"interrupts.c",
- "mailbox.c",
"mailbox_common.c",
"memory_sharing.c",
"no_services.c",
diff --git a/test/vmapi/primary_with_secondaries/mailbox.c b/test/vmapi/primary_with_secondaries/mailbox.c
deleted file mode 100644
index d9597a6..0000000
--- a/test/vmapi/primary_with_secondaries/mailbox.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2019 The Hafnium Authors.
- *
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/BSD-3-Clause.
- */
-
-#include <stdint.h>
-
-#include "hf/ffa.h"
-#include "hf/std.h"
-
-#include "vmapi/hf/call.h"
-
-#include "primary_with_secondary.h"
-#include "test/hftest.h"
-#include "test/vmapi/ffa.h"
-
-/**
- * Causes secondary VM to send two messages to primary VM. The second message
- * will reach the mailbox while it's not writable. Checks that notifications are
- * properly delivered when mailbox is cleared.
- */
-TEST(mailbox, primary_to_secondary)
-{
- char message[] = "not ready echo";
- struct ffa_value run_res;
- struct mailbox_buffers mb = set_up_mailbox();
-
- SERVICE_SELECT(SERVICE_VM1, "echo_with_notification", mb.send);
-
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Send a message to echo service, and get response back. */
- memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
- EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
-
- /* Let secondary VM continue running so that it will wait again. */
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Without clearing our mailbox, send message again. */
- reverse(message, strnlen_s(message, sizeof(message)));
- memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
-
- /* Message should be dropped since the mailbox was not cleared. */
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, HF_FFA_RUN_WAIT_FOR_INTERRUPT);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Clear the mailbox. We expect to be told there are pending waiters. */
- EXPECT_EQ(ffa_rx_release().func, FFA_RX_RELEASE_32);
-
- /* Retrieve a single waiter. */
- EXPECT_EQ(hf_mailbox_waiter_get(HF_PRIMARY_VM_ID), SERVICE_VM1);
- EXPECT_EQ(hf_mailbox_waiter_get(HF_PRIMARY_VM_ID), -1);
-
- /*
- * Inject interrupt into VM and let it run again. We should receive
- * the echoed message.
- */
- EXPECT_EQ(
- hf_interrupt_inject(SERVICE_VM1, 0, HF_MAILBOX_WRITABLE_INTID),
- 1);
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
- EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
- EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
-}
diff --git a/test/vmapi/primary_with_secondaries/mailbox_common.c b/test/vmapi/primary_with_secondaries/mailbox_common.c
index 5ae3265..aabd68f 100644
--- a/test/vmapi/primary_with_secondaries/mailbox_common.c
+++ b/test/vmapi/primary_with_secondaries/mailbox_common.c
@@ -208,52 +208,3 @@
EXPECT_EQ(ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, 0, 0).func,
FFA_SUCCESS_32);
}
-
-/**
- * Sends two messages to secondary VM without letting it run, so second message
- * won't go through. Ensure that a notification is delivered when secondary VM
- * clears the mailbox.
- */
-TEST(mailbox, secondary_to_primary_notification)
-{
- const char message[] = "not ready echo";
- struct ffa_value run_res;
- struct mailbox_buffers mb = set_up_mailbox();
-
- SERVICE_SELECT(SERVICE_VM1, "echo_with_notification", mb.send);
-
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_WAIT_32);
- EXPECT_EQ(run_res.arg2, FFA_SLEEP_INDEFINITE);
-
- /* Send a message to echo service twice. The second should fail. */
- memcpy_s(mb.send, FFA_MSG_PAYLOAD_MAX, message, sizeof(message));
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
- EXPECT_FFA_ERROR(ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1,
- sizeof(message), FFA_MSG_SEND_NOTIFY),
- FFA_BUSY);
-
- /* Receive a reply for the first message. */
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_MSG_SEND_32);
- EXPECT_EQ(ffa_msg_send_size(run_res), sizeof(message));
- EXPECT_EQ(memcmp(mb.recv, message, sizeof(message)), 0);
- EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
-
- /* Run VM again so that it clears its mailbox. */
- run_res = ffa_run(SERVICE_VM1, 0);
- EXPECT_EQ(run_res.func, FFA_RX_RELEASE_32);
-
- /* Retrieve a single waiter. */
- EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM1), HF_PRIMARY_VM_ID);
- EXPECT_EQ(hf_mailbox_waiter_get(SERVICE_VM1), -1);
-
- /* Send should now succeed. */
- EXPECT_EQ(
- ffa_msg_send(HF_PRIMARY_VM_ID, SERVICE_VM1, sizeof(message), 0)
- .func,
- FFA_SUCCESS_32);
-}
diff --git a/test/vmapi/primary_with_secondaries/services/BUILD.gn b/test/vmapi/primary_with_secondaries/services/BUILD.gn
index 7f8e8e3..da7cfc2 100644
--- a/test/vmapi/primary_with_secondaries/services/BUILD.gn
+++ b/test/vmapi/primary_with_secondaries/services/BUILD.gn
@@ -50,20 +50,6 @@
]
}
-# Echo service that waits for recipient to become writable.
-source_set("echo_with_notification") {
- testonly = true
- public_configs = [ "//test/hftest:hftest_config" ]
-
- sources = [
- "echo_with_notification.c",
- ]
-
- deps = [
- "//src/arch/aarch64/hftest:interrupts",
- ]
-}
-
# Service for floating point register save/restore checks.
source_set("floating_point") {
testonly = true
@@ -232,7 +218,6 @@
":check_state",
":debug_el1",
":echo",
- ":echo_with_notification",
":ffa_check",
":floating_point",
":interruptible",
diff --git a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c b/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
deleted file mode 100644
index a4027f0..0000000
--- a/test/vmapi/primary_with_secondaries/services/echo_with_notification.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2018 The Hafnium Authors.
- *
- * Use of this source code is governed by a BSD-style
- * license that can be found in the LICENSE file or at
- * https://opensource.org/licenses/BSD-3-Clause.
- */
-
-#include "hf/arch/irq.h"
-#include "hf/arch/vm/interrupts.h"
-
-#include "hf/ffa.h"
-#include "hf/std.h"
-
-#include "vmapi/hf/call.h"
-
-#include "../msr.h"
-#include "test/hftest.h"
-
-static void irq(void)
-{
- hf_interrupt_get();
-}
-
-static void wait_for_vm(uint32_t vmid)
-{
- for (;;) {
- int64_t w = hf_mailbox_writable_get();
- if (w == vmid) {
- return;
- }
-
- if (w == -1) {
- interrupt_wait();
- arch_irq_enable();
- arch_irq_disable();
- }
- }
-}
-
-TEST_SERVICE(echo_with_notification)
-{
- exception_setup(irq, NULL);
- hf_interrupt_enable(HF_MAILBOX_WRITABLE_INTID, true,
- INTERRUPT_TYPE_IRQ);
-
- /* Loop, echo messages back to the sender. */
- for (;;) {
- void *send_buf = SERVICE_SEND_BUFFER();
- void *recv_buf = SERVICE_RECV_BUFFER();
- struct ffa_value ret = ffa_msg_wait();
- ffa_vm_id_t target_vm_id = ffa_receiver(ret);
- ffa_vm_id_t source_vm_id = ffa_sender(ret);
-
- memcpy_s(send_buf, FFA_MSG_PAYLOAD_MAX, recv_buf,
- ffa_msg_send_size(ret));
-
- while (ffa_msg_send(target_vm_id, source_vm_id,
- ffa_msg_send_size(ret), FFA_MSG_SEND_NOTIFY)
- .func != FFA_SUCCESS_32) {
- wait_for_vm(source_vm_id);
- }
-
- EXPECT_EQ(ffa_rx_release().func, FFA_SUCCESS_32);
- }
-}