/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* This file contains preset event names from the Performance Application
* Programming Interface v3.5 which included the following notice:
*
* Copyright (c) 2005,6
* Innovative Computing Labs
* Computer Science Department,
* University of Tennessee,
* Knoxville, TN.
* All Rights Reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* * Neither the name of the University of Tennessee nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* This open source software license conforms to the BSD License template.
*/
/*
* Niagara Performance Counter Backend
*/
#include <sys/cpc_impl.h>
#include <sys/cpc_pcbe.h>
#include <sys/machsystm.h>
#include <sys/niagararegs.h>
static int ni_pcbe_init(void);
static uint_t ni_pcbe_ncounters(void);
static const char *ni_pcbe_impl_name(void);
static const char *ni_pcbe_cpuref(void);
static char *ni_pcbe_list_attrs(void);
static uint64_t ni_pcbe_overflow_bitmap(void);
void *token);
static void ni_pcbe_program(void *token);
static void ni_pcbe_allstop(void);
static void ni_pcbe_sample(void *token);
static void ni_pcbe_free(void *config);
extern void ultra_setpcr(uint64_t);
extern uint64_t ultra_getpcr(void);
extern void ultra_setpic(uint64_t);
extern uint64_t ultra_getpic(void);
extern uint64_t ultra_gettick(void);
};
typedef struct _ni_pcbe_config {
struct nametable {
const char *name;
};
typedef struct _ni_generic_events {
char *name;
char *event;
{0x00, "Instr_cnt"},
{NT_END, ""}
};
{0x0, "SB_full"},
{0x1, "FP_instr_cnt"},
{0x2, "IC_miss"},
{0x3, "DC_miss"},
{0x4, "ITLB_miss"},
{0x5, "DTLB_miss"},
{0x6, "L2_imiss"},
{0x7, "L2_dmiss_ld"},
{NT_END, ""}
};
};
{ "PAPI_tot_ins", "Instr_cnt" },
};
{ "PAPI_l2_icm", "L2_imiss" },
{ "PAPI_l2_ldm", "L2_dmiss_ld" },
{ "PAPI_fp_ops", "FP_instr_cnt" },
{ "PAPI_fp_ins", "FP_instr_cnt" },
{ "PAPI_l1_icm", "IC_miss" },
{ "PAPI_l1_dcm", "DC_miss" },
{ "PAPI_tlb_im", "ITLB_miss" },
{ "PAPI_tlb_dm", "DTLB_miss" },
};
};
"for descriptions of these events." CPU_REF_URL;
static int
ni_pcbe_init(void)
{
const struct nametable *n;
int i;
/*
* Initialize the list of events for each PIC.
* Do two passes: one to compute the size necessary and another
* to copy the strings. Need room for event, comma, and NULL terminator.
*/
for (i = 0; i < 2; i++) {
size = 0;
*pic_events[i] = '\0';
}
}
/*
* Remove trailing comma.
*/
}
return (0);
}
static uint_t
ni_pcbe_ncounters(void)
{
return (2);
}
static const char *
ni_pcbe_impl_name(void)
{
return (ni_impl_name);
}
static const char *
ni_pcbe_cpuref(void)
{
return (niagara_cpuref);
}
static char *
{
return (pic_events[picnum]);
}
static char *
ni_pcbe_list_attrs(void)
{
return ("");
}
static const ni_generic_event_t *
{
return (gevp);
}
return (NULL);
}
static const struct nametable *
{
const struct nametable *n;
return (n);
return (NULL);
}
static uint64_t
{
bitmap = 0x1;
bitmap |= 0x2;
return (bitmap);
}
/*
* These processors cannot tell which counter overflowed. The PCBE interface
* requires such processors to act as if _all_ counters had overflowed.
*/
static uint64_t
ni_pcbe_overflow_bitmap(void)
{
pcr = ultra_getpcr();
#if 0
/*
* Not needed if the CPC framework is responsible to stop counters
* and that action ends up clearing overflow flags.
*/
if (overflow)
#endif
return (overflow);
}
/*ARGSUSED*/
static int
{
const struct nametable *n;
/*
* If we've been handed an existing configuration, we need only preset
* the counter value.
*/
return (0);
}
return (CPC_INVALID_PICNUM);
if (nattrs != 0)
return (CPC_INVALID_ATTRIBUTE);
/*
* Find other requests that will be programmed with this one, and ensure
* the flags don't conflict.
*/
return (CPC_CONFLICTING_REQS);
} else {
return (CPC_INVALID_EVENT);
}
}
return (0);
}
static void
{
NULL)
}
if (pic0->pcbe_picno != 0) {
/*
* pic0 is counter 1, so if we need the empty config it should
* be counter 0.
*/
empty.pcbe_picno = 0;
#if 0
/* no selection for counter 0 */
#endif
}
/*
* UltraSPARC does not allow pic0 to be configured differently
* from pic1. If the flags on these two configurations are
* different, they are incompatible. This condition should be
* caught at configure time.
*/
/*
* On UltraSPARC, only read-to-read counts are accurate. We cannot
* expect the value we wrote into the PIC, above, to be there after
* starting the counter. We must sample the counter value now and use
* that as the baseline for future samples.
*/
curpic = ultra_getpic();
}
static void
ni_pcbe_allstop(void)
{
}
static void
{
curpic = ultra_getpic();
}
if (pic0->pcbe_picno != 0) {
empty.pcbe_picno = 0;
}
if (diff < 0)
if (diff < 0)
}
static void
{
}
"UltraSPARC T1 Performance Counters",
};
&modlpcbe,
};
int
_init(void)
{
if (ni_pcbe_init() != 0)
return (ENOTSUP);
return (mod_install(&modl));
}
int
_fini(void)
{
return (mod_remove(&modl));
}
int
{
}