123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- /*
- * Copyright (c) 2014-2018 Remy Noel.
- * Copyright (c) 2014-2018 Richard Braun.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- * Performance monitoring based on hardware performance counters.
- *
- * The hardware layer is represented by a performance monitoring unit (PMU),
- * which provides performance monitoring counters (PMCs).
- */
- #ifndef KERN_PERFMON_H
- #define KERN_PERFMON_H
- #include <stdint.h>
- #include <kern/init.h>
- #include <kern/perfmon_types.h>
- #include <kern/thread.h>
- // IDs of generic performance monitoring events.
- #define PERFMON_EV_CYCLE 0
- #define PERFMON_EV_REF_CYCLE 1
- #define PERFMON_EV_INSTRUCTION 2
- #define PERFMON_EV_CACHE_REF 3
- #define PERFMON_EV_CACHE_MISS 4
- #define PERFMON_EV_BRANCH 5
- #define PERFMON_EV_BRANCH_MISS 6
- #define PERFMON_NR_GENERIC_EVENTS 7
- // Event flags.
- #define PERFMON_EF_KERN 0x1 // Monitor events in kernel mode.
- #define PERFMON_EF_USER 0x2 // Monitor events in user mode.
- #define PERFMON_EF_RAW 0x4 // Raw event ID, generic if unset.
- /*
- * Performance monitoring operations.
- *
- * This is a public structure.
- *
- * All operations are either global but serialized by the caller, or
- * processor-local and called with interrupts and preemption disabled.
- *
- * If the hardware doesn't efficiently support overflow interrupts, the
- * handler must be set to NULL, making the perfmon module perdiocally
- * check the raw value of the hardware counters.
- */
- struct perfmon_dev_ops
- {
- /*
- * Convert a generic event ID into a raw event ID.
- *
- * Global operation.
- */
- int (*translate) (unsigned int *, unsigned int);
- /*
- * Allocate a performance monitoring counter globally for the given
- * raw event ID, and return the counter ID through the given pointer.
- * The driver may return any PMC ID, as long as it uniquely identifies
- * the underlying counter. The PMC index is passed when reporting
- * overflows, if using a custom overflow interrupt handler.
- *
- * Global operation.
- */
- int (*alloc) (unsigned int *, unsigned int, unsigned int);
- /*
- * Free an allocated performance monitoring counter.
- *
- * Global operation.
- */
- void (*free) (unsigned int);
- /*
- * Start a performance monitoring counter for the given raw event ID.
- *
- * Processor-local operation.
- */
- void (*start) (unsigned int, unsigned int);
- /*
- * Stop a performance monitoring counter.
- *
- * Processor-local operation.
- */
- void (*stop) (unsigned int);
- /*
- * Read the value of a performance monitoring counter.
- *
- * Processor-local operation.
- */
- uint64_t (*read) (unsigned int);
- /*
- * Custom overflow interrupt handler.
- *
- * Processor-local operation.
- */
- void (*handle_overflow_intr) (void);
- };
- /*
- * Performance monitoring device.
- *
- * This is a public structure.
- *
- * The PMC width is expressed in bits.
- *
- * If the driver doesn't provide an overflow interrupt handler, it may set
- * the poll interval, in ticks, to a duration that safely allows the detection
- * of a single overflow. A value of 0 lets the perfmon module compute a poll
- * interval itself.
- */
- struct perfmon_dev
- {
- const struct perfmon_dev_ops *ops;
- unsigned int pmc_width;
- uint64_t poll_interval;
- };
- // Performance monitoring thread data.
- struct perfmon_td;
- /*
- * Performance monitoring event.
- *
- * An event describes a single, well-defined hardware condition and tracks
- * its occurrences over a period of time.
- */
- struct perfmon_event;
- // Initialize thread-specific data.
- void perfmon_td_init (struct perfmon_td *td);
- /*
- * Load/unload events attached to a thread on the current processor.
- *
- * These functions should only be used by the scheduler on a context switch.
- * Interrupts and preemption must be disabled when calling these functions.
- */
- void perfmon_td_load (struct perfmon_td *td);
- void perfmon_td_unload (struct perfmon_td *td);
- // Initialize an event.
- int perfmon_event_init (struct perfmon_event *event, unsigned int id,
- unsigned int flags);
- /*
- * Attach/detach an event to/from a thread or a processor.
- *
- * Attaching an event allocates hardware resources and enables monitoring.
- * The number of occurrences for the given event is reset.
- *
- * An event can only be attached to one thread or processor at a time.
- */
- int perfmon_event_attach (struct perfmon_event *event, struct thread *thread);
- int perfmon_event_attach_cpu (struct perfmon_event *event, unsigned int cpu);
- int perfmon_event_detach (struct perfmon_event *event);
- // Obtain the number of occurrences of an event.
- uint64_t perfmon_event_read (struct perfmon_event *event);
- /*
- * Register a PMU device.
- *
- * Currently, there can only be a single system-wide PMU device, which
- * assumes the driver is the same for all processors.
- */
- void perfmon_register (struct perfmon_dev *dev);
- /*
- * Handle an overflow interrupt.
- *
- * This function must be called in interrupt context.
- */
- void perfmon_overflow_intr (void);
- /*
- * Report a PMC overflow.
- *
- * This function is intended to be used by PMU drivers using a custom
- * overflow interrupt handler.
- *
- * This function must be called in interrupt context.
- */
- void perfmon_report_overflow (unsigned int pmc_index);
- /*
- * This init operation provides :
- * - PMU device registration
- */
- INIT_OP_DECLARE (perfmon_bootstrap);
- #endif
|