aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-09-22 08:32:10 +0100
committerJeenu Viswambharan <jeenu.viswambharan@arm.com>2017-10-23 08:15:11 +0100
commit8e743bcd6a69bce2ac782319951061c69798558d (patch)
treeb22a4b955653830c53203f21ea11b98350fbf338
parentf911e229f3ab0481230cf1e03bc0c076707c9567 (diff)
downloadarm-trusted-firmware-8e743bcd6a69bce2ac782319951061c69798558d.tar.gz
BL31: Introduce Publish and Subscribe framework
This light-weight framework enables some EL3 components to publish events which other EL3 components can subscribe to. Publisher can optionally pass opaque data for subscribers. The order in which subscribers are called is not defined. Firmware design updated. Change-Id: I24a3a70b2b1dedcb1f73cf48313818aebf75ebb6 Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
-rw-r--r--bl31/bl31.ld.S8
-rw-r--r--bl32/sp_min/sp_min.ld.S8
-rw-r--r--docs/firmware-design.rst81
-rw-r--r--include/lib/el3_runtime/pubsub.h84
-rw-r--r--include/lib/el3_runtime/pubsub_events.h12
5 files changed, 193 insertions, 0 deletions
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 48861f40..9ff774b6 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -62,6 +62,10 @@ SECTIONS
KEEP(*(cpu_ops))
__CPU_OPS_END__ = .;
+ /* Place pubsub sections for events */
+ . = ALIGN(8);
+#include <pubsub_events.h>
+
. = NEXT(4096);
__RODATA_END__ = .;
} >RAM
@@ -95,6 +99,10 @@ SECTIONS
KEEP(*(cpu_ops))
__CPU_OPS_END__ = .;
+ /* Place pubsub sections for events */
+ . = ALIGN(8);
+#include <pubsub_events.h>
+
*(.vectors)
__RO_END_UNALIGNED__ = .;
/*
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index d0fb4a03..fc44d524 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -50,6 +50,10 @@ SECTIONS
KEEP(*(cpu_ops))
__CPU_OPS_END__ = .;
+ /* Place pubsub sections for events */
+ . = ALIGN(8);
+#include <pubsub_events.h>
+
. = NEXT(4096);
__RODATA_END__ = .;
} >RAM
@@ -75,6 +79,10 @@ SECTIONS
KEEP(*(cpu_ops))
__CPU_OPS_END__ = .;
+ /* Place pubsub sections for events */
+ . = ALIGN(8);
+#include <pubsub_events.h>
+
*(.vectors)
__RO_END_UNALIGNED__ = .;
diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst
index 07905975..8851065a 100644
--- a/docs/firmware-design.rst
+++ b/docs/firmware-design.rst
@@ -2258,6 +2258,87 @@ should consider the trade-off between memory footprint and security.
This build flag is disabled by default, minimising memory footprint. On ARM
platforms, it is enabled.
+Publish and Subscribe Framework
+-------------------------------
+
+The Publish and Subscribe Framework allows EL3 components to define and publish
+events, to which other EL3 components can subscribe.
+
+The following macros are provided by the framework:
+
+- ``REGISTER_PUBSUB_EVENT(event)``: Defines an event, and takes one argument,
+ the event name, which must be a valid C identifier. All calls to
+ ``REGISTER_PUBSUB_EVENT`` macro must be placed in the file
+ ``pubsub_events.h``.
+
+- ``PUBLISH_EVENT_ARG(event, arg)``: Publishes a defined event, by iterating
+ subscribed handlers and calling them in turn. The handlers will be passed the
+ parameter ``arg``. The expected use-case is to broadcast an event.
+
+- ``PUBLISH_EVENT(event)``: Like ``PUBLISH_EVENT_ARG``, except that the value
+ ``NULL`` is passed to subscribed handlers.
+
+- ``SUBSCRIBE_TO_EVENT(event, handler)``: Registers the ``handler`` to
+ subscribe to ``event``. The handler will be executed whenever the ``event``
+ is published.
+
+- ``for_each_subscriber(event, subscriber)``: Iterates through all handlers
+ subscribed for ``event``. ``subscriber`` must be a local variable of type
+ ``pubsub_cb_t *``, and will point to each subscribed handler in turn during
+ iteration. This macro can be used for those patterns that none of the
+ ``PUBLISH_EVENT_*()`` macros cover.
+
+Publishing an event that wasn't defined using ``REGISTER_PUBSUB_EVENT`` will
+result in build error. Subscribing to an undefined event however won't.
+
+Subscribed handlers must be of type ``pubsub_cb_t``, with following function
+signature:
+
+::
+
+ typedef void* (*pubsub_cb_t)(const void *arg);
+
+There may be arbitrary number of handlers registered to the same event. The
+order in which subscribed handlers are notified when that event is published is
+not defined. Subscribed handlers may be executed in any order; handlers should
+not assume any relative ordering amongst them.
+
+Publishing an event on a PE will result in subscribed handlers executing on that
+PE only; it won't cause handlers to execute on a different PE.
+
+Note that publishing an event on a PE blocks until all the subscribed handlers
+finish executing on the PE.
+
+Publish and Subscribe Example
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A publisher that wants to publish event ``foo`` would:
+
+- Define the event ``foo`` in the ``pubsub_events.h``.
+
+ ::
+
+ REGISTER_PUBSUB_EVENT(foo);
+
+- Depending on the nature of event, use one of ``PUBLISH_EVENT_*()`` macros to
+ publish the event at the appropriate path and time of execution.
+
+A subscriber that wants to subscribe to event ``foo`` published above would
+implement:
+
+::
+
+ void *foo_handler(const void *arg)
+ {
+ void *result;
+
+ /* Do handling ... */
+
+ return result;
+ }
+
+ SUBSCRIBE_TO_EVENT(foo, foo_handler);
+
Performance Measurement Framework
---------------------------------
diff --git a/include/lib/el3_runtime/pubsub.h b/include/lib/el3_runtime/pubsub.h
new file mode 100644
index 00000000..9a854808
--- /dev/null
+++ b/include/lib/el3_runtime/pubsub.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PUBSUB_H__
+#define __PUBSUB_H__
+
+#define __pubsub_start_sym(event) __pubsub_##event##_start
+#define __pubsub_end_sym(event) __pubsub_##event##_end
+
+#ifdef __LINKER__
+
+/* For the linker ... */
+
+#define __pubsub_section(event) __pubsub_##event
+
+/*
+ * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler
+ * contexts. In linker context, this collects pubsub sections for each event,
+ * placing guard symbols around each.
+ */
+#define REGISTER_PUBSUB_EVENT(event) \
+ __pubsub_start_sym(event) = .; \
+ KEEP(*(__pubsub_section(event))); \
+ __pubsub_end_sym(event) = .
+
+#else /* __LINKER__ */
+
+/* For the compiler ... */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <cdefs.h>
+#include <stddef.h>
+
+#define __pubsub_section(event) __section("__pubsub_" #event)
+
+/*
+ * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols
+ * exported by the linker required for the other pubsub macros to work.
+ */
+#define REGISTER_PUBSUB_EVENT(event) \
+ extern pubsub_cb_t __pubsub_start_sym(event)[]; \
+ extern pubsub_cb_t __pubsub_end_sym(event)[]
+
+/*
+ * Have the function func called back when the specified event happens. This
+ * macro places the function address into the pubsub section, which is picked up
+ * and invoked by the invoke_pubsubs() function via. the PUBLISH_EVENT* macros.
+ */
+#define SUBSCRIBE_TO_EVENT(event, func) \
+ pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = func
+
+/*
+ * Iterate over subscribed handlers for a defined event. 'event' is the name of
+ * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'.
+ */
+#define for_each_subscriber(event, subscriber) \
+ for (subscriber = __pubsub_start_sym(event); \
+ subscriber < __pubsub_end_sym(event); \
+ subscriber++)
+
+/*
+ * Publish a defined event supplying an argument. All subscribed handlers are
+ * invoked, but the return value of handlers are ignored for now.
+ */
+#define PUBLISH_EVENT_ARG(event, arg) \
+ do { \
+ pubsub_cb_t *subscriber; \
+ for_each_subscriber(event, subscriber) { \
+ (*subscriber)(arg); \
+ } \
+ } while (0)
+
+/* Publish a defined event with NULL argument */
+#define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL)
+
+/* Subscriber callback type */
+typedef void* (*pubsub_cb_t)(const void *arg);
+
+#endif /* __LINKER__ */
+#endif /* __PUBSUB_H__ */
diff --git a/include/lib/el3_runtime/pubsub_events.h b/include/lib/el3_runtime/pubsub_events.h
new file mode 100644
index 00000000..8ef1a11b
--- /dev/null
+++ b/include/lib/el3_runtime/pubsub_events.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <pubsub.h>
+
+/*
+ * This file defines a list of pubsub events, declared using
+ * REGISTER_PUBSUB_EVENT() macro.
+ */