blob: 2c8f5841f985bcbb9dd1ae53d3473494a6cc97d1 [file]
/*
* Copyright 2014, NICTA
*
* This software may be distributed and modified according to the terms of
* the BSD 2-Clause license. Note that NO WARRANTY is provided.
* See "LICENSE_BSD2.txt" for details.
*
* @TAG(NICTA_BSD)
*/
#ifndef __SEL4BENCH_H__
#define __SEL4BENCH_H__
#include <stddef.h>
#include <stdint.h>
#include <sel4/sel4.h>
#include <sel4bench/arch/sel4bench.h>
#define SEL4BENCH_API static __attribute__((unused))
/**
* @file
*
* libsel4bench is a library designed to abstract over the performance
* monitoring counters (PMCs) in modern IA-32 and ARM processors, so that you
* can measure the performance of your software. It will also work out whether
* certain operations need to be done in kernel mode, and perform kernel code
* injection calls to make them happen. As a result, expect that any library
* call could potentially result in a syscall. (This is of particular note on
* the ARM1136, for which even reading the cycle counter must be done in kernel
* mode.)
*
* It also goes out of its way to ensure that there's always a cycle counter
* available for use. _init() will start this running, and _destroy() will tear
* it down, if necessary.
*
* Finally, some CPP constants for events that are common to all architecture
* variants are also exposed. These are:
* <ul>
* <li> SEL4BENCH_EVENT_CACHE_L1I_MISS </li>
* <li> SEL4BENCH_EVENT_CACHE_L1D_MISS </li>
* <li> SEL4BENCH_EVENT_TLB_L1I_MISS </li>
* <li> SEL4BENCH_EVENT_TLB_L1D_MISS </li>
* <li> SEL4BENCH_EVENT_MEMORY_ACCESS </li>
* <li> SEL4BENCH_EVENT_EXECUTE_INSTRUCTION </li>
* <li> SEL4BENCH_EVENT_BRANCH_MISPREDICT </li>
* </ul>
* Additional events are architecture (and potentially processor) specific.
* These may be defined in architecture or processor header files.
*
* See the events.h for your architecture for specific events, caveats,
* gotchas, and other trickery.
*
* Notes:
* - The MEMORY_ACCESS event refers to all memory loads/stores issued by the
* processor -- that is, all memory accesses *except* instruction fetch
* operations -- whether they are satisfied by a cache or from main memory.
* - Overflow is completely ignored, even on processors that only support
* 32-bit counters (and thus where there is space to overflow into). If you
* are doing something that might overflow a counter, it's up to you to deal
* with that possibility.
* - Everything is zero-indexed.
*/
/**
* Initialise the sel4bench library. Nothing else is guaranteed to work, and
* may produce strange failures, if you don't do this first.
* Starts the cycle counter, which is guaranteed to run until _destroy() is
* called.
*/
SEL4BENCH_API void sel4bench_init();
/**
* Tear down the sel4bench library. Nothing else is guaranteed to work, and may
* produce strange failures, after you do this.
*/
SEL4BENCH_API void sel4bench_destroy();
/**
* Query the cycle counter. If said counter needs starting, _init() will have
* taken care of it.
*
* @return The current cycle count. This might be since _init(), if the cycle
* counter needs explicit starting, or since bootup, if it freewheels.
*/
SEL4BENCH_API sel4bench_counter_t sel4bench_get_cycle_count();
/**
* Query how many performance counters are supported on this CPU, excluding the
* cycle counter.
*
* @return Processor's available counters.
*/
SEL4BENCH_API seL4_Word sel4bench_get_num_counters();
/**
* Query the value of a counter.
*
* @param counter The counter to query.
* @return The value of the counter.
*/
SEL4BENCH_API sel4bench_counter_t sel4bench_get_counter(seL4_Word counter);
/**
* Query the value of a set of counters.
*
* @param counters A bitfield indicating which counter(s) to query.
* @param values An array of sel4bench_counter_t, of length equal to the
* highest counter index to be read (to a maximum of
* sel4bench_get_num_counters()). Each counter to be read
* will be written to its corresponding index in this array.
* @return The current cycle count, as sel4bench_get_cycle_count()
*/
SEL4BENCH_API sel4bench_counter_t sel4bench_get_counters(seL4_Word counters, sel4bench_counter_t* values);
/**
* Assign a counter to track a specific event. Events are processor-specific,
* though some common ones might be exposed through preprocessor constants.
*
* @param counter The counter to configure.
* @param event The event to track.
*/
SEL4BENCH_API void sel4bench_set_count_event(seL4_Word counter, seL4_Word event);
/**
* Start counting events on a set of performance counters. The argument is a
* bitfield detailing that set. (Note that this means the library supports a
* number of counters less than or equal to the machine word size in bits.)
*
* @param counters A bitfield indicating which counter(s) to start.
*/
SEL4BENCH_API void sel4bench_start_counters(seL4_Word counters);
/**
* Stop counting events on a set of performance counters. The argument is a
* bitfield detailing that set. (Note that this means the library supports a
* number of counters less than or equal to the machine word size in bits.)
*
* Some processors (notably, the ARM1136) may not support this operation.
*
* @param counters A bitfield indicating which counter(s) to stop.
*/
SEL4BENCH_API void sel4bench_stop_counters(seL4_Word counters);
/**
* Reset a set of performance counters to zero. The argument is a
* bitfield detailing that set. (Note that this means the library supports a
* number of counters less than or equal to the machine word size in bits.)
*
* @param counters A bitfield indicating which counter(s) to reset.
*/
SEL4BENCH_API void sel4bench_reset_counters(seL4_Word counters);
#endif /* __SEL4BENCH_H__ */