#ifndef _SYS_XC_IMPL_H
#define _SYS_XC_IMPL_H
#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _ASM
#include <sys/note.h>
#include <sys/cpu_module.h>
#include <sys/panic.h>
extern cpuset_t cpu_ready_set;
extern void send_self_xcall(struct cpu *, uint64_t, uint64_t, xcfunc_t *);
extern uint_t xc_loop(void);
extern uint_t xc_serv(void);
extern void xc_stop(struct regs *);
#ifdef TRAPTRACE
extern void xc_trace(uint_t, cpuset_t *, xcfunc_t *, uint64_t, uint64_t);
#endif
extern uint64_t xc_func_time_limit;
extern uint_t sendmondo_in_recover;
#ifdef sun4v
#define XT_SYNC_ONE(cpuid) \
{ \
cpuset_t set; \
CPUSET_ONLY(set, cpuid); \
xt_sync(set); \
}
#define XT_SYNC_SOME(cpuset) \
{ \
xt_sync(cpuset); \
}
#else
#define XT_SYNC_ONE(cpuid) \
{ \
init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \
send_one_mondo(cpuid); \
}
#define XT_SYNC_SOME(cpuset) \
{ \
init_mondo((xcfunc_t *)xt_sync_tl1, 0, 0); \
send_mondo_set(cpuset); \
}
#endif
#define XC_SPL_ENTER(cpuid, opl) \
{ \
opl = splr(XCALL_PIL); \
cpuid = CPU->cpu_id; \
if (xc_spl_enter[cpuid] && !panic_quiesce) \
cmn_err(CE_PANIC, "XC SPL ENTER already entered (0x%x)",\
cpuid); \
xc_spl_enter[cpuid] = 1; \
}
#define XC_SPL_EXIT(cpuid, opl) \
{ \
ASSERT(xc_spl_enter[cpuid] != 0); \
xc_spl_enter[cpuid] = 0; \
splx(opl); \
}
#define XC_SETUP(cpuid, func, arg1, arg2) \
{ \
xc_mbox[cpuid].xc_func = func; \
xc_mbox[cpuid].xc_arg1 = arg1; \
xc_mbox[cpuid].xc_arg2 = arg2; \
xc_mbox[cpuid].xc_state = XC_DOIT; \
}
#define SEND_MBOX_ONLY(xc_cpuset, func, arg1, arg2, lcx, state) \
{ \
int pix; \
cpuset_t tmpset = xc_cpuset; \
for (pix = 0; pix < NCPU; pix++) { \
if (CPU_IN_SET(tmpset, pix)) { \
ASSERT(MUTEX_HELD(&xc_sys_mutex)); \
ASSERT(CPU_IN_SET(xc_mbox[lcx].xc_cpuset, pix));\
ASSERT(xc_mbox[pix].xc_state == state); \
XC_SETUP(pix, func, arg1, arg2); \
membar_stld(); \
CPUSET_DEL(tmpset, pix); \
CPU_STATS_ADDQ(CPU, sys, xcalls, 1); \
if (CPUSET_ISNULL(tmpset)) \
break; \
} \
} \
}
#define SEND_MBOX_MONDO(xc_cpuset, func, arg1, arg2, state) \
{ \
int pix; \
cpuset_t tmpset = xc_cpuset; \
for (pix = 0; pix < NCPU; pix++) { \
if (CPU_IN_SET(tmpset, pix)) { \
ASSERT(xc_mbox[pix].xc_state == state); \
XC_SETUP(pix, func, arg1, arg2); \
CPUSET_DEL(tmpset, pix); \
if (CPUSET_ISNULL(tmpset)) \
break; \
} \
} \
membar_stld(); \
send_mondo_set(xc_cpuset); \
}
#define SEND_MBOX_MONDO_XC_ENTER(xc_cpuset) \
{ \
int pix; \
cpuset_t tmpset = xc_cpuset; \
for (pix = 0; pix < NCPU; pix++) { \
if (CPU_IN_SET(tmpset, pix)) { \
ASSERT(xc_mbox[pix].xc_state == \
XC_IDLE); \
xc_mbox[pix].xc_state = XC_ENTER; \
CPUSET_DEL(tmpset, pix); \
if (CPUSET_ISNULL(tmpset)) { \
break; \
} \
} \
} \
send_mondo_set(xc_cpuset); \
}
#define WAIT_MBOX_DONE(xc_cpuset, lcx, state, sync) \
{ \
int pix; \
uint64_t loop_cnt = 0; \
cpuset_t tmpset; \
cpuset_t recv_cpuset; \
int first_time = 1; \
CPUSET_ZERO(recv_cpuset); \
while (!CPUSET_ISEQUAL(recv_cpuset, xc_cpuset)) { \
tmpset = xc_cpuset; \
for (pix = 0; pix < NCPU; pix++) { \
if (CPU_IN_SET(tmpset, pix)) { \
if (xc_mbox[pix].xc_state == state) { \
CPUSET_ADD(recv_cpuset, pix); \
} \
} \
CPUSET_DEL(tmpset, pix); \
if (CPUSET_ISNULL(tmpset)) \
break; \
} \
if (loop_cnt++ > xc_func_time_limit) { \
if (sendmondo_in_recover) { \
drv_usecwait(1); \
loop_cnt = 0; \
continue; \
} \
_NOTE(CONSTANTCONDITION) \
if (sync && first_time) { \
XT_SYNC_SOME(xc_cpuset); \
first_time = 0; \
loop_cnt = 0; \
continue; \
} \
panic("WAIT_MBOX_DONE() timeout, " \
"recv_cpuset 0x%lx, xc cpuset 0x%lx ", \
*(ulong_t *)&recv_cpuset, \
*(ulong_t *)&xc_cpuset); \
} \
} \
}
enum xc_states {
XC_IDLE = 0,
XC_ENTER,
XC_WAIT,
XC_DOIT,
XC_EXIT
};
#define PC_ALIGN 4
#ifdef TRAPTRACE
#define XC_TRACE(type, cpus, func, arg1, arg2) \
xc_trace((type), (cpus), (func), (arg1), (arg2))
#else
#define XC_TRACE(type, cpus, func, arg1, arg2)
#endif
#if defined(DEBUG) || defined(TRAPTRACE)
#define XC_STAT_INC(a) (a)++;
#define XC_CPUID 0
#define XT_ONE_SELF 1
#define XT_ONE_OTHER 2
#define XT_SOME_SELF 3
#define XT_SOME_OTHER 4
#define XT_ALL_SELF 5
#define XT_ALL_OTHER 6
#define XC_ONE_SELF 7
#define XC_ONE_OTHER 8
#define XC_ONE_OTHER_H 9
#define XC_SOME_SELF 10
#define XC_SOME_OTHER 11
#define XC_SOME_OTHER_H 12
#define XC_ALL_SELF 13
#define XC_ALL_OTHER 14
#define XC_ALL_OTHER_H 15
#define XC_ATTENTION 16
#define XC_DISMISSED 17
#define XC_LOOP_ENTER 18
#define XC_LOOP_DOIT 19
#define XC_LOOP_EXIT 20
extern uint_t x_dstat[NCPU][XC_LOOP_EXIT+1];
extern uint_t x_rstat[NCPU][4];
#define XC_LOOP 1
#define XC_SERV 2
#define XC_STAT_INIT(cpuid) \
{ \
x_dstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \
x_rstat[cpuid][XC_CPUID] = 0xffffff00 | cpuid; \
}
#else
#define XC_STAT_INIT(cpuid)
#define XC_STAT_INC(a)
#define XC_ATTENTION_CPUSET(x)
#define XC_DISMISSED_CPUSET(x)
#endif
#endif
#define XC_SEND_MONDO_MSEC 1000
#ifdef __cplusplus
}
#endif
#endif