NAME
pfm_dispatch_events - determine PMC registers values for a set of
events to measure
SYNOPSIS
#include <perfmon/pfmlib.h>
int pfm_dispatch_events(pfmlib_input_param_t *p, void *mod_in, pfmlib_output_param_t *q,void *mod_out);
DESCRIPTION
This function is the central piece of the library. It is important to
understand that the library does not effectively program the PMU, i.e.,
it does not make the operating system calls. The PMU is never actually
accessed by the library. Instead, the library helps applications
prepare the arguments to pass to the kernel. In particular, it sets up
the values to program into the PMU configuration registers (PMC). The
list of used data registers (PMD) is also returned.
The input argument are divided into two categories: the generic
arguments in p and the optional PMU model specific arguments in mod_in.
The same applies for the output arguments: q contains the generic
output arguments and mod_out the optional PMU model specific arguments.
An application describes what it wants to measure in the in and if it
uses some model specific features, such as opcode matching on Itanium 2
processors, it must pass a pointer to the relevant model-specific input
parameters in mod_in. The generic output parameters contains the
register index and values for the PMC and PMD registers needed to make
the measurement. The index mapping is guaranteed to match the mapping
used by the Linux perfmon2 interface. In case the library is not used
on this system, the hardware register addresses or indexes can also be
retrieved from the output structure.
The pfmlib_input_param_t structure is defined as follows:
typedef struct
int event;
unsigned int plm;
unsigned long flags;
unsigned int unit_masks[PFMLIB_MAX_MASKS_PER_EVENT];
unsigned int num_masks;
} pfmlib_event_t;
typedef struct {
unsigned int pfp_event_count;
unsigned int pfp_dfl_plm;
unsigned int pfp_flags;
pfmlib_event_t pfp_events[PFMLIB_MAX_PMCS];
pfmlib_regmask_t pfp_unavail_pmcs;
} pfmlib_input_param_t;
The structure mostly contains one table, called pfp_events which
describes the events to be measured. The number of submitted events is
indicated by pfp_event_count.
Each event is described in the pfp_events table by an opaque descriptor
stored in the event field. This descriptor is obtained with the
pfm_find_full_event() or derivative functions. For some events, it may
be necessary to specify at least one unit mask in the unit_masks table.
A unit mask is yet another opaque descriptor obtained via
pfm_find_event_mask() or pfm_find_full_event. Typically, if an event
supports multiple unit masks, they can be combined in which case more
than one entry in unit_masks must be specified. The actual number of
unit mask descriptors passed must be indicated in num_masks. When no
unit mask is used, this field must be set to 0.
A privilege level mask for the event can be provided in plm. This is a
bitmask where each bit indicates a privilege level at which to monitor,
more than one bit can be set. The library supports up to four levels,
but depending on the PMU model, some levels may not be available. The
levels are as follows:
PFM_PLM0
monitor at the privilege level 0. For many architectures, this
means kernel level
PFM_PLM1
monitor at privilege level 1
PFM_PLM2
monitor at privilege level 2
PFM_PLM3
monitor at the privilege level 3. For many architectures, this
means user level
Events with a plm value of 0 will use the default privilege level mask
as indicated by pfp_dfl_plm which must be set to any combinations of
values described above. It is illegal to have a value of 0 for this
field.
The pfp_flags field contains a set of flags that affect the whole set
of events to be monitored. The currently defined flags are:
PFMLIB_PFP_SYSTEMWIDE
indicates that the monitors are to be used in a system-wide
monitoring session. This could influence the way the library
sets up some register values.
The pfp_unavail_pmcs bitmask can be used by applications to communicate
to the library the list of PMC registers which are not available on the
system. Some kernels may allocate certain PMC registers (and
associated data registers) for other purposes. Those registers must not
be used by the library otherwise the assignement of events to PMC
registers may be rejected by the kernel. Applications must figure out
which registers are available using a kernel interface at their
disposal, the library does not provide this service. The library expect
the restrictions to be expressed using the Linux perfmon2 PMC register
mapping.
Refer to the PMU specific manual for a description of the model-
specific input parameters to be passed in mod_in.
The generic output parameters are contained in the
fBpfmlib_output_param_t structure which is defined as:
typedef struct {
unsigned long long reg_value;
unsigned int reg_num;
unsigned long reg_addr;
} pfmlib_reg_t;
typedef struct {
unsigned int pfp_pmc_count;
unsigned int pfp_pmd_count;
pfmlib_reg_t pfp_pmcs[PFMLIB_MAX_PMCS];
pfmlib_reg_t pfp_pmds[PFMLIB_MAX_PMDS];
} pfmlib_output_param_t;
The number of valid entries in the pfp_pmcs table is indicated by
pfp_pmc_count. The number of valid entries in the pfp_pmds table is
indicated by pfp_pmd_count. Each entry in both tables is of type
pfmlib_reg_t.
In the pfp_pmcs table, the reg_num contains the PMC register index
(perfmon2 mapping), and the reg_value contains a 64-bit value to be
used to program the PMC register. The reg_addr indicates the hardware
address or index for the PMC register.
In the pfp_pmds table, the reg_num contains the PMD register index
(perfmon2 mapping). the reg_value is ignored. The reg_addr indicates
the hardware address or index for the PMC register.
Refer to the PMU specific manual for a description of the model-
specific output parameters to be returned in mod_out.
The current implementation of the pfm_dispatch_events completely
overwrites the pfmlib_output_param structure. In other words, results
do not accumulate into the pfp_pmcs table across multiple calls. Unused
fields are guaranteed to be zeroed upon successful return.
Depending on the PMU model, there may not always be a one to one
mapping between a PMC register and a data register. Register
dependencies may be more intricate. However the pfm_dispatch_events
guarantees certain ordering between the pfp_pmcs and pfp_pmds tables.
In particular, it guarantees that the pfp_pmds table always starts with
the counters corresponding, in the same order, to the events as
provided in the pfp_event table on input. There is always one counter
per event. Additional PMD registers, if any, come after.
EXAMPLE
Here is a typical sequence using the perfmon2 interface:
#include <perfmon/pfmlib.h>
...
pfmlib_input_param_t inp;
pfmlib_output_param_t outp;
pfarg_ctx_t ctx;
pfarg_pmd_t pd[1];
pfarg_pmc_t pc[1];
pfarg_load_t load_arg;
int fd, i;
int ret;
if (pfm_initialize() != PFMLIB_SUCCESS) {
fprintf(stderr, "can’t initialize library\n");
exit(1);
}
memset(&ctx,0, sizeof(ctx));
memset(&inp,0, sizeof(inp));
memset(&outp,0, sizeof(outp));
memset(pd, 0, sizeof(pd));
memset(pc, 0, sizeof(pc));
memset(&load_arg, 0, sizeof(load_arg));
ret = pfm_get_cycle_event(&inp.pfp_events[0]);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot find cycle event\n");
exit(1);
}
inp.pfp_dfl_plm = PFM_PLM3;
inp.pfp_event_count = 1;
ret = pfm_dispatch_events(&inp, NULL, &outp, NULL);
if (ret != PFMLIB_SUCCESS) {
fprintf(stderr, "cannot dispatch events: %s\n", pfm_strerror(ret));
exit(1);
}
/* propagate pmc value to perfmon2 structures */
for(i=0; i < outp.pfp_pmc_count; i++) {
pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
}
for(i=0; i < outp.pfp_pmd_count; i++) {
pd[i].reg_num = outp.pfp_pmds[i].reg_num;
pd[i].reg_value = 0;
}
...
if (pfm_create_context(&ctx, NULL, 0) == -1 ) {
...
}
fd = ctx.ctx_fd;
if (pfm_write_pmcs(fd, pc, outp.pfp_pmc_count) == -1) {
...
}
if (pfm_write_pmds(fd, pd, outp.pfp_pmd_count) == -1) {
...
}
load_arg.load_pid = getpid();
if (pfm_load_context(fd, &load_arg) == -1) {
...
}
pfm_start(fd, NULL);
/* code to monitor */
pfm_stop(fd);
if (pfm_read_pmds(fd, pd, evt.pfp_event_count) == -1) {
...
}
printf("results: %llu0, pd[0].reg_value);
...
close(fd);
...
RETURN
The function returns whether or not the call was successful. A return
value of PFMLIB_SUCCESS indicates sucess, otherwise the value is the
error code.
ERRORS
PFMLIB_ERR_NOINIT The library has not been initialized properly.
PFMLIB_ERR_INVAL
Some arguments were invalid. For instance the value of *count is
zero. This can also be due to he content of the pfmlib_param_t
structure.
PFMLIB_ERR_NOTFOUND
No matching event was found.
PFMLIB_ERR_TOOMANY
The number of events to monitor exceed the number of implemented
counters.
PFMLIB_ERR_NOASSIGN
The events cannot be dispatched to the PMC because events have
conflicting constraints.
PFMLIB_ERR_MAGIC
The model specific extension does not have the right magic
number.
PFMLIB_ERR_FEATCOMB
The set of events and features cannot be combined.
PFMLIB_ERR_EVTMANY
An event has been supplied more than once and is causing
resource (PMC) conflicts.
PFMLIB_ERR_IRRINVAL
Invalid code range restriction (Itanium, Itanium 2).
PFMLIB_ERR_IRRALIGN
Code range has invalid alignment (Itanium, Itanium 2).
PFMLIB_ERR_IRRTOOMANY
Cannot satisfy all the code ranges (Itanium, Itanium 2).
PFMLIB_ERR_DRRTOOMANY
Cannot satisfy all the data ranges (Itanium, Itanium 2).
PFMLIB_ERR_DRRINVAL
Invalid data range restriction (Itanium, Itanium 2).
PFMLIB_ERR_EVTSET
Some events belong to incompatible sets (Itanium 2).
PFMLIB_ERR_EVTINCOMP
Some events cannot be measured at the same time (Itanium 2).
PFMLIB_ERR_IRRTOOBIG
Code range is too big (Itanium 2).
PFMLIB_ERR_UMASK
Invalid or missing unit mask.
SEE ALSO
libpfm_itanium(3), libpfm_itanium2(3), pfm_regmask_set(3),
pfm_regmask_clr(3), pfm_find_event_code_mask(3)
AUTHOR
Stephane Eranian <eranian@hpl.hp.com>
July , 2003 LIBPFM(3)