summaryrefslogtreecommitdiff
path: root/big-little/lib/virt_events.c
diff options
context:
space:
mode:
Diffstat (limited to 'big-little/lib/virt_events.c')
-rw-r--r--big-little/lib/virt_events.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/big-little/lib/virt_events.c b/big-little/lib/virt_events.c
new file mode 100644
index 0000000..2765278
--- /dev/null
+++ b/big-little/lib/virt_events.c
@@ -0,0 +1,120 @@
+/*
+ * $Copyright:
+ * ----------------------------------------------------------------
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2011 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ * ----------------------------------------------------------------
+ * File: virt_events.c
+ * ----------------------------------------------------------------
+ * $
+ */
+
+#include "events.h"
+#include "misc.h"
+#include "virt_helpers.h"
+
+/*
+ * cpu ids are used as is when "switcher" is true. In the
+ * "always on" case absolute cpu ids are used i.e 0-7 for
+ * an MPx4+MPx4 configuration.
+ */
+/*
+ * Pick up the event definition from the world that wants
+ * to use them.
+ */
+extern unsigned event[][MAX_EVENTS];
+
+/*
+ * Set the specified event for that cpu.
+ */
+void set_event(unsigned event_id, unsigned cpu_id)
+{
+ dsb();
+ event[cpu_id][event_id] = TRUE;
+ dsb();
+ sev();
+ return;
+}
+
+inline unsigned get_event(unsigned event_id, unsigned cpu_id)
+{
+ return event[cpu_id][event_id];
+}
+
+void reset_event(unsigned event_id, unsigned cpu_id)
+{
+ dsb();
+ event[cpu_id][event_id] = FALSE;
+ dsb();
+ return;
+}
+
+void wait_for_event(unsigned event_id, unsigned cpu_id)
+{
+ dsb();
+ while (FALSE == get_event(event_id, cpu_id)) {
+ wfe();
+ isb();
+ dsb();
+ }
+
+ return;
+}
+
+/*
+ * Wait for events from each core. Its a little trickier than
+ * waiting for a single event. The event register as per the
+ * architecture is just a single bit to flag an event rather
+ * than the number of events. If multiple events are sent by
+ * the time we enter wfe() then each flag variable should be
+ * checked.
+ */
+void wait_for_events(unsigned event_id)
+{
+ unsigned ctr, event_count = 0, num_cpus = 0;
+
+ if (switcher) {
+ num_cpus = num_secondaries() + 1;
+ } else {
+ num_cpus = CLUSTER_CPU_COUNT(host_cluster)
+ + CLUSTER_CPU_COUNT(!host_cluster);
+ }
+
+ do {
+ for (ctr = 0; ctr < num_cpus; ctr++) {
+ if (TRUE == get_event(event_id, ctr)) {
+ event_count++;
+ reset_event(event_id, ctr);
+ }
+ }
+
+ if (event_count != num_cpus)
+ wfe();
+ else
+ break;
+ } while(1);
+
+ return;
+}
+
+void set_events(unsigned event_id)
+{
+ unsigned ctr, num_cpus = 0;
+
+ if (switcher) {
+ num_cpus = num_secondaries() + 1;
+ } else {
+ num_cpus = CLUSTER_CPU_COUNT(host_cluster)
+ + CLUSTER_CPU_COUNT(!host_cluster);
+ }
+
+ for (ctr = 0; ctr < num_cpus; ctr++) {
+ set_event(event_id, ctr);
+ }
+ return;
+}