cbe.c revision 454ab20244cd84c2b93aa273b462eab1166cf539
/*
* 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.
*/
#include <sys/cyclic_impl.h>
#include <sys/machsystm.h>
#include <sys/smp_impldefs.h>
#include <sys/psm_types.h>
#include <sys/x86_archext.h>
#include <sys/ddi_impldefs.h>
#include <sys/ddi_intr.h>
static int cbe_vector;
static int cbe_ticks = 0;
/*
* cbe_xcall_lock is used to protect the xcall globals since the cyclic
* reprogramming API does not use cpu_lock.
*/
static kmutex_t cbe_xcall_lock;
static cyc_func_t volatile cbe_xcall_func;
static cpu_t *volatile cbe_xcall_cpu;
static void *cbe_xcall_farg;
static cpuset_t cbe_enabled;
static ddi_softint_hdl_impl_t cbe_low_hdl =
static ddi_softint_hdl_impl_t cbe_clock_hdl =
int cbe_psm_timer_mode = TIMER_ONESHOT;
static hrtime_t cbe_timer_resolution;
extern int tsc_gethrtime_enable;
void cbe_hres_tick(void);
int
cbe_softclock(void)
{
return (1);
}
int
cbe_low_level(void)
{
return (1);
}
/*
* We can be in cbe_fire() either due to a cyclic-induced cross call, or due
* to the timer firing at level-14. Because cyclic_fire() can tolerate
* spurious calls, it would not matter if we called cyclic_fire() in both
* cases.
*/
int
cbe_fire(void)
{
for (i = 1; i < NCPU; i++) {
if (CPU_IN_SET(cbe_enabled, i)) {
send_dirint(i, CBE_HIGH_PIL);
}
}
}
if (cross_call) {
}
return (1);
}
/*ARGSUSED*/
void
{
switch (level) {
case CY_LOW_LEVEL:
break;
case CY_LOCK_LEVEL:
break;
default:
}
}
/*ARGSUSED*/
void
{
if (cbe_psm_timer_mode == TIMER_ONESHOT)
(*psm_timer_reprogram)(time);
}
/*ARGSUSED*/
{
int ipl;
switch (level) {
case CY_LOW_LEVEL:
ipl = CBE_LOW_PIL;
break;
case CY_LOCK_LEVEL:
ipl = CBE_LOCK_PIL;
break;
case CY_HIGH_LEVEL:
ipl = CBE_HIGH_PIL;
break;
default:
}
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
void
{
return;
}
continue;
}
void *
{
return (cpu);
}
#ifndef __xpv
/*
* declarations needed for time adjustment
*/
extern void tsc_suspend(void);
extern void tsc_resume(void);
/*
* Call the resume function in the cyclic, instead of inline in the
* resume path.
*/
extern int tsc_resume_in_cyclic;
#endif
/*ARGSUSED*/
static void
{
#ifndef __xpv
/*
* This is an x86 backend, so let the tsc_suspend
* that is specific to x86 platforms do the work.
*/
tsc_suspend();
#endif
}
/*ARGSUSED*/
static void
{
#ifndef __xpv
if (tsc_resume_in_cyclic) {
tsc_resume();
}
#endif
}
void
cbe_enable(void *arg)
{
/* neither enable nor disable cpu0 if TIMER_PERIODIC is set */
return;
/*
* Added (me == 0) to the ASSERT because the timer isn't
* disabled on CPU 0, and cbe_enable is called when we resume.
*/
if (cbe_psm_timer_mode == TIMER_ONESHOT)
(*psm_timer_enable)();
}
void
cbe_disable(void *arg)
{
/* neither enable nor disable cpu0 if TIMER_PERIODIC is set */
return;
if (cbe_psm_timer_mode == TIMER_ONESHOT)
(*psm_timer_disable)();
}
/*
* Unbound cyclic, called once per tick (every nsec_per_tick ns).
*/
void
cbe_hres_tick(void)
{
int s;
/*
* Because hres_tick effectively locks hres_lock, we must be at the
* same PIL as that used for CLOCK_LOCK.
*/
hres_tick();
splx(s);
(*hrtime_tick)();
cbe_ticks++;
}
void
cbe_init_pre(void)
{
}
void
cbe_init(void)
{
cyc_backend_t cbe = {
cbe_configure, /* cyb_configure */
NULL, /* cyb_unconfigure */
cbe_enable, /* cyb_enable */
cbe_disable, /* cyb_disable */
cbe_reprogram, /* cyb_reprogram */
cbe_softint, /* cyb_softint */
cbe_set_level, /* cyb_set_level */
cbe_restore_level, /* cyb_restore_level */
cbe_xcall, /* cyb_xcall */
cbe_suspend, /* cyb_suspend */
cbe_resume /* cyb_resume */
};
if (psm_get_ipivect != NULL) {
"cbe_fire_slave",
}
if (psm_post_cyclic_setup != NULL)
}