root/usr/src/uts/common/sys/cap_util.h
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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.
 */

#ifndef _SYS_CAP_UTIL_H
#define _SYS_CAP_UTIL_H


#ifdef  __cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/kcpc.h>
#include <sys/cpc_impl.h>
#include <sys/pghw.h>
#include <sys/cmt.h>

#ifdef  _KERNEL

/*
 * Capacity and utilization flags for each CPU
 */
#define CU_CPU_CNTRS_ON         1       /* CPU performance counters are on */
#define CU_CPU_CNTRS_OFF_ON     2       /* Off -> on transition */

/*
 * Macro that returns whether CPU performance counters turned on for given CPU
 */
#define CU_CPC_ON(cp) \
        ((cp) != NULL && (cp)->cpu_cu_info != NULL && \
            ((cp)->cpu_cu_info->cu_flag & CU_CPU_CNTRS_ON))


/*
 * Per counter statistics
 */
typedef struct cu_cntr_stats {
        hrtime_t        cs_time_running; /* running total of time counting */
        hrtime_t        cs_time_stopped; /* ... time not counting */
        hrtime_t        cs_time_start;  /* start time of current sample  */
        uint64_t        cs_value_start; /* starting value for next sample */
        uint64_t        cs_value_last;  /* last value */
        uint64_t        cs_value_total; /* running total */
        uint64_t        cs_rate;        /* observed rate since last */
        uint64_t        cs_rate_max;    /* maximum rate */
        kcpc_request_t  *cs_cpc_req;    /* corresponding CPC request */
        struct cpu      *cs_cpu_start;  /* CPU where starting value gotten */
} cu_cntr_stats_t;


/*
 * Counter info for a PG hardware sharing relationship
 */
typedef struct cu_cntr_info {
        cpu_t           *ci_cpu;        /* CPU being measured */
        pghw_t          *ci_pg;         /* hardware PG being measured */
        kstat_t         *ci_kstat;      /* kstats being exported */
        cu_cntr_stats_t *ci_stats;      /* counter statistics */
        uint_t          ci_nstats;      /* number of statistics */
} cu_cntr_info_t;


/*
 * Each CPU can have one or more CPC contexts for measuring capacity and
 * utilization
 *
 * One CPC context is needed per CPU if the counter events needed to measure
 * capacity and utilization on each CPU can be programmed onto all the counters
 * on a CPU at the same time and there are fewer or same number of desired
 * counter events as counters on each CPU.  Otherwise, the desired counter
 * events are assigned across multiple CPC contexts, so the contexts and their
 * counter events can be multiplexed onto the counters over time to get the
 * data for all of the counter events.
 */
typedef struct cu_cpc_ctx {
        int             cur_index;      /* index for current context */
        int             nctx;           /* number of CPC contexts */
        kcpc_ctx_t      **ctx_ptr_array; /* array of context pointers */
        size_t          ctx_ptr_array_sz; /* size of array */
} cu_cpc_ctx_t;

/*
 * Per CPU capacity and utilization info
 */
typedef struct cu_cpu_info {
        struct cpu      *cu_cpu;        /* CPU for the statistics */
        uint_t          cu_flag;        /* capacity & utilization flag */
        hrtime_t        cu_sample_time; /* when last sample taken */
        cu_cpc_ctx_t    cu_cpc_ctx;     /* performance counter contexts */
        cu_cntr_stats_t *cu_cntr_stats; /* counter statistics array */
        uint_t          cu_ncntr_stats; /* number of counter statistics */
        uint_t          cu_disabled;    /* count of disable requests */
        /*
         * Per PG hardware sharing relationship counter info
         */
        cu_cntr_info_t  *cu_cntr_info[PGHW_NUM_COMPONENTS];
} cu_cpu_info_t;

/*
 * COMMON INTERFACE ROUTINES
 */

/*
 * Setup capacity and utilization support
 */
extern void     cu_init(void);

/*
 * Tear down capacity and utilization support
 */
extern int      cu_fini(void);

/*
 * Program CPC for capacity and utilization on given CPU
 */
extern void     cu_cpc_program(struct cpu *, int *);

/*
 * Unprogram CPC for capacity and utilization on given CPU
 */
extern void     cu_cpc_unprogram(struct cpu *, int *);

/*
 * Update counter statistics on a given CPU
 */
extern int      cu_cpu_update(struct cpu *, boolean_t);

/*
 * Update utilization and capacity data for CMT PG
 */
extern void     cu_pg_update(pghw_t *);

/*
 * Disable or enable capacity and utilization on all CPUs
 */
extern void     cu_disable(void);
extern void     cu_enable(void);

/*
 * PLATFORM SPECIFIC INTERFACE ROUTINES
 */
extern int      cu_plat_cpc_init(cpu_t *, kcpc_request_list_t *, int);

#endif  /* _KERNEL */

#ifdef  __cplusplus
}
#endif

#endif /* _SYS_CAP_UTIL_H */