cmd_Lxcache.c revision 7bebe46c240b554f47faeed19186123896281967
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Support routines for managing per-Lxcache state.
*/
#include <cmd_Lxcache.h>
#include <cmd_mem.h>
#include <cmd_cpu.h>
#include <cmd.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <strings.h>
#include <sys/cheetahregs.h>
#include <sys/mem_cache.h>
#define PN_ECSTATE_NA 5
/*
* These values are our threshold values for SERDing CPU's based on the
* the # of times we have retired a cache line for each category.
*/
#define CMD_CPU_SERD_AGG_1 64
#define CMD_CPU_SERD_AGG_2 64
static void
{
sizeof (cmd_Lxcache_pers_t));
}
void
int destroy)
{
}
}
if (destroy)
}
void
{
}
static cmd_Lxcache_t *
{
return (Lxcache);
}
return (NULL);
}
{
const char *pstype_name;
"creating new Lxcache for cachetype=%d index=%lx way=%lx bit=%x\n",
switch (pstype) {
case CMD_PTR_CPU_L2DATA:
pstype_name = "l2data";
break;
case CMD_PTR_CPU_L3DATA:
pstype_name = "l3data";
break;
case CMD_PTR_CPU_L2TAG:
pstype_name = "l2tag";
break;
case CMD_PTR_CPU_L3TAG:
pstype_name = "l3tag";
break;
default:
pstype_name = "unknown";
break;
}
index)) != 0 ||
way)) != 0 ||
bit)) != 0 ||
fmri_Lxcache_type)) != 0 ||
return (Lxcache);
}
{
return (cache);
}
}
return (NULL);
}
{
bit));
}
static cmd_Lxcache_t *
{
if (psz != sizeof (cmd_Lxcache_pers_t)) {
"version 1 state (%u bytes).\n",
sizeof (cmd_Lxcache_pers_t));
}
return (Lxcache);
}
void *
{
char *serdnm;
/*
* We need to first extract the cpu name by reading directly
* from fmd buffers in order to begin our search for Lxcache in
* the appropriate cpu list.
* After we identify the cpu list using buf name we could look
* in cpu list for our Lxcache states.
*/
"not exist in saved state\n",
} else if (Lxcachesz != sizeof (cmd_Lxcache_pers_t)) {
"is %d bytes. Expected size is %d bytes\n",
sizeof (cmd_Lxcache_pers_t));
}
}
break;
}
switch (recovered_Lxcache->Lxcache_version) {
case CMD_LxCACHE_VERSION_1:
break;
default:
"for Lxcache state referenced by case %s.\n",
break;
}
}
"cpu_id %d: serdname for the case is %s\n",
"cpu_id %d: restoring the case for index %d way %d bit %d\n",
return (Lxcache);
}
/*ARGSUSED*/
void
{
}
}
}
void
{
sizeof (cmd_Lxcache_pers_t))
/* No need to rewrite the FMRIs in the Lxcache - they don't change */
sizeof (cmd_Lxcache_pers_t));
}
void
{
}
char *
{
const char *fmt = "cpu_%d:%s_%08d_%02d_%03d_serd";
const char *serdbase;
char *nm;
switch (pstype) {
case CMD_PTR_CPU_L2DATA:
serdbase = "l2data";
break;
case CMD_PTR_CPU_L3DATA:
serdbase = "l3data";
break;
case CMD_PTR_CPU_L2TAG:
serdbase = "l2tag";
break;
case CMD_PTR_CPU_L3TAG:
serdbase = "l3tag";
break;
default:
serdbase = "unknown";
break;
}
return (nm);
}
/*
* Count the number of SERD type 2 ways retired for a given cpu
* These are defined to be L3 Cache data retirements
*/
{
ret_count++;
}
}
return (ret_count);
}
/*
* Count the number of SERD type 1 ways retired for a given cpu
* These are defined to be L2 Data, tag and L3 Tag retirements
*/
{
ret_count++;
}
}
return (ret_count);
}
void
const char *fltnm)
{
fmd_case_t *cp;
const char *uuid;
&uuid);
}
void
{
char fltnm[64];
int cpu_retired_1, cpu_retired_2;
return;
}
/* Retrieve the number of retired ways for each category */
if ((cpu_retired_1 > CMD_CPU_SERD_AGG_1) ||
(cpu_retired_2 > CMD_CPU_SERD_AGG_2) &&
type);
}
}
void
{
cmd_case_t *cc;
Lxcache->Lxcache_cpu_bufname) == 0)
break;
}
/*
* We will destroy the case and serd engine.
* The rest will be destroyed when we retire the CPU
* until then we keep the Lxcache strutures alive.
*/
}
}
}
void
{
}
{
int fd;
if (fd == -1) {
(void) printf(
"cpu_id = %d could not open %s to read tag info.\n",
return (CMD_EVD_BAD);
}
switch (pstype) {
case CMD_PTR_CPU_L2TAG:
case CMD_PTR_CPU_L2DATA:
break;
case CMD_PTR_CPU_L3TAG:
case CMD_PTR_CPU_L3DATA:
break;
}
cache_info.way = 0;
if (test_mode) {
== -1) {
(void) printf("cpu_id = %d ioctl"
" MEM_CACHE_READ_ERROR_INJECTED_TAGS failed"
" errno = %d\n",
return (CMD_EVD_BAD);
}
} else {
== -1) {
(void) printf("cpu_id = %d ioctl"
" MEM_CACHE_READ_TAGS failed"
" errno = %d\n",
return (CMD_EVD_BAD);
}
}
return (CMD_EVD_OK);
}
int
{
if (fd == -1) {
(void) printf("Error in opening file %s,Errno = %d\n",
return (-1);
}
switch (pstype) {
case CMD_PTR_CPU_L2TAG:
case CMD_PTR_CPU_L2DATA:
break;
case CMD_PTR_CPU_L3TAG:
case CMD_PTR_CPU_L3DATA:
break;
}
retired_ways = 0;
cache_info.way = 0;
perror("ioctl MEM_CACHE_READ_TAGS failed\n");
return (-1);
}
for (i = 0; i < PN_CACHE_NWAYS; i++) {
if ((tag_data[i] & CH_ECSTATE_MASK) ==
retired_ways++;
}
}
return (retired_ways);
}
int
{
int i, retired_ways;
return (-1);
}
retired_ways = 0;
for (i = 0; i < PN_CACHE_NWAYS; i++) {
if ((tag_data[i] & CH_ECSTATE_MASK) ==
retired_ways++;
}
return (retired_ways);
}
int
{
return (-1);
}
return (1);
return (0);
}