diff options
Diffstat (limited to 'big-little/lib/virt_events.c')
-rw-r--r-- | big-little/lib/virt_events.c | 120 |
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; +} |