Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
adam.huang
Arm Trusted Firmware
Commits
4c37ac89
Commit
4c37ac89
authored
Oct 23, 2017
by
davidcunado-arm
Committed by
GitHub
Oct 23, 2017
Browse files
Merge pull request #1132 from jeenu-arm/pubsub
Publish and Subscribe framework
parents
f911e229
bd0c3477
Changes
6
Hide whitespace changes
Inline
Side-by-side
bl31/bl31.ld.S
View file @
4c37ac89
...
...
@@ -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__
=
.
;
/
*
...
...
bl32/sp_min/sp_min.ld.S
View file @
4c37ac89
...
...
@@ -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__
=
.
;
...
...
docs/firmware-design.rst
View file @
4c37ac89
...
...
@@ -2258,6 +2258,103 @@ 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);
Available Events
~~~~~~~~~~~~~~~~
ARM Trusted Firmware core makes some events available by default. They're listed
below, along with information as to when they're published, and the arguments
passed to subscribed handlers.
Other EL3 components that are conditionally compiled in may make their own
events available, but aren't documented here.
- ``psci_cpu_on_finish``
- When: Published on a PE after it's finished its power-up sequence.
- Argument: ``NULL``.
Performance Measurement Framework
---------------------------------
...
...
include/lib/el3_runtime/pubsub.h
0 → 100644
View file @
4c37ac89
/*
* 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__ */
include/lib/el3_runtime/pubsub_events.h
0 → 100644
View file @
4c37ac89
/*
* 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.
*/
/*
* Event published after a CPU has been powered up and finished its
* initialization.
*/
REGISTER_PUBSUB_EVENT
(
psci_cpu_on_finish
);
lib/psci/psci_on.c
View file @
4c37ac89
...
...
@@ -11,6 +11,7 @@
#include <context_mgmt.h>
#include <debug.h>
#include <platform.h>
#include <pubsub_events.h>
#include <stddef.h>
#include "psci_private.h"
...
...
@@ -188,6 +189,8 @@ void psci_cpu_on_finish(unsigned int cpu_idx,
if
(
psci_spd_pm
&&
psci_spd_pm
->
svc_on_finish
)
psci_spd_pm
->
svc_on_finish
(
0
);
PUBLISH_EVENT
(
psci_cpu_on_finish
);
/* Populate the mpidr field within the cpu node array */
/* This needs to be done only once */
psci_cpu_pd_nodes
[
cpu_idx
].
mpidr
=
read_mpidr
()
&
MPIDR_AFFINITY_MASK
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment