event_ultra.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Routines to capture processor-dependencies in event specification.
*/
#include <string.h>
#include <strings.h>
#include <alloca.h>
#include <stdlib.h>
#include <stdio.h>
#include <libintl.h>
#include <assert.h>
#include "libcpc.h"
#include "libcpc_impl.h"
/*
* Event specifications for UltraSPARC performance counters are based
* on the content of a getsubopt-like string.
* The string should contain something that looks like this:
*
* pic0=<eventspec>,pic1=<eventspec>
* [,nouser][,sys]
*
* For example:
* pic1=0x4,pic0=Instr_cnt
* or
* pic0=Instr_cnt,pic1=Cycle_cnt,nouser,sys
*
* The two events must be named. The names can be ascii or
* a decimal, octal or hexadecimal number as parsed by strtol(3C).
*
* By default, user event counting is enabled, system event counting
* is disabled.
*
* The routine counts the number of errors encountered while parsing
* the string, if no errors are encountered, the event handle is
* returned.
*/
const char *
cpc_getusage(int cpuver)
{
switch (cpuver) {
case CPC_ULTRA1:
case CPC_ULTRA2:
case CPC_ULTRA3:
case CPC_ULTRA3_PLUS:
case CPC_ULTRA3_I:
return ("pic0=<event0>,pic1=<event1> "
"[,sys] "
"[,nouser]");
default:
return (NULL);
}
}
/*
* This private structure is used to build tables that correspond
* to the bit patterns in the control registers of the processor.
*/
struct keyval {
char *kv_token;
int (*kv_action)(const char *,
int kv_shift;
};
static int
{
return (-1);
}
return (-1);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (-1);
}
return (0);
}
/*ARGSUSED*/
static int
{
return (-1);
}
return (0);
}
/*
* This token table must match the keyval tables below.
*/
static char * const tokens[] = {
#define D_pic0 0
"pic0", /* takes a valid event name */
#define D_pic1 1
"pic1", /* takes a valid event name */
#define D_nouser 2
"nouser", /* disables user counts */
#define D_sys 3
"sys", /* enables system counts */
};
static const struct keyval us2_keyvals[] = {
{ "pic0", picbits,
{ "pic1", picbits,
{ "nouser", bitclr,
{ "sys", bitset,
};
static const struct keyval us3_keyvals[] = {
{ "pic0", picbits,
{ "pic1", picbits,
{ "nouser", bitclr,
{ "sys", bitset,
};
#if !defined(NDEBUG)
#pragma init(__tablecheck)
static void
__tablecheck(void)
{
uint_t n;
for (n = 0; n < ntokens; n++)
for (n = 0; n < us2_nkeys; n++)
}
#endif /* !NDEBUG */
int
{
static const char fn[] = "strtoevent";
char *value;
char *pic[2];
char *opts;
int errcnt = 0;
return (errcnt = 1);
case CPC_ULTRA1:
case CPC_ULTRA2:
break;
case CPC_ULTRA3:
case CPC_ULTRA3_PLUS:
case CPC_ULTRA3_I:
break;
default:
return (errcnt = 1);
}
while (*opts != '\0') {
errcnt++;
break;
}
"repeated '%s' token\n",
errcnt++;
break;
}
"repeated '%s' token\n",
errcnt++;
break;
}
}
} else if (idx == -1) {
/*
* The token given wasn't recognized.
* See if it was an implicit pic specification..
*/
errcnt++;
break;
}
errcnt++;
break;
}
} else {
errcnt++;
break;
}
} else {
if (idx >= 0 &&
else
errcnt++;
break;
}
}
errcnt++;
}
return (errcnt);
}
/*
* Return a printable description of the control registers.
*
* This routine should always succeed (notwithstanding heap problems),
* but may not be able to correctly decode the registers, if, for
* example, a new processor is under test.
*
* The caller is responsible for free(3c)ing the string returned.
*/
static char *
{
}
static char *
{
const char *sname;
}
struct xpcr {
};
static void
{
switch (cpuver) {
case CPC_ULTRA1:
case CPC_ULTRA2:
default:
kv = us2_keyvals;
break;
case CPC_ULTRA3:
case CPC_ULTRA3_PLUS:
case CPC_ULTRA3_I:
kv = us3_keyvals;
break;
}
}
char *
{
char *pic[2];
char buffer[1024];
case CPC_ULTRA1:
case CPC_ULTRA2:
case CPC_ULTRA3:
case CPC_ULTRA3_PLUS:
case CPC_ULTRA3_I:
break;
default:
return (NULL);
}
return (NULL);
return (NULL);
}
}
/*
* Utility operations on events
*/
void
{
}
void
{
}
/*
* Given a cpc_event_t and cpc_bind_event() flags, translate the event into the
* cpc_set_t format.
*
* Returns NULL on failure.
*/
{
char *pic[2];
case CPC_ULTRA1:
case CPC_ULTRA2:
case CPC_ULTRA3:
case CPC_ULTRA3_PLUS:
case CPC_ULTRA3_I:
break;
default:
return (NULL);
}
return (NULL);
return (NULL);
}
flag |= CPC_COUNT_USER;
flag |= CPC_COUNT_SYSTEM;
if (iflags & CPC_BIND_EMT_OVF)
goto bad;
1, &attr) != 0)
goto bad;
goto bad;
return (set);
bad:
return (NULL);
}