#define __INTR_PRIVATE
#include <sys/param.h>
#include <sys/intr.h>
#include <sys/cpu.h>
#include <sys/atomic.h>
#ifdef __HAVE_FAST_SOFTINTS
#include <powerpc/softint.h>
__CTASSERT(IPL_NONE < IPL_SOFTCLOCK);
__CTASSERT(IPL_SOFTCLOCK < IPL_SOFTBIO);
__CTASSERT(IPL_SOFTBIO < IPL_SOFTNET);
__CTASSERT(IPL_SOFTNET < IPL_SOFTSERIAL);
__CTASSERT(IPL_SOFTSERIAL < IPL_VM);
__CTASSERT(IPL_SOFTSERIAL < sizeof(uint32_t)*2);
static inline void
softint_deliver(struct cpu_info *ci, int ipl)
{
const int si_level = IPL2SOFTINT(ipl);
KASSERT(ci->ci_data.cpu_softints & (1 << ipl));
ci->ci_data.cpu_softints ^= 1 << ipl;
softint_fast_dispatch(ci->ci_softlwps[si_level], ipl);
KASSERTMSG(ci->ci_cpl == IPL_HIGH,
"%s: cpl (%d) != HIGH", __func__, ci->ci_cpl);
}
void
powerpc_softint(struct cpu_info *ci, int old_ipl, vaddr_t pc)
{
const u_int softint_mask = (IPL_SOFTMASK << old_ipl) & IPL_SOFTMASK;
u_int softints;
KASSERTMSG(ci->ci_idepth == -1,
"%s: cpu%u: idepth (%d) != -1", __func__,
cpu_index(ci), ci->ci_idepth);
KASSERT(ci->ci_mtx_count == 0);
KASSERT(ci->ci_cpl == IPL_HIGH);
while ((softints = (ci->ci_data.cpu_softints & softint_mask)) != 0) {
KASSERT(old_ipl < IPL_SOFTSERIAL);
if (softints & (1 << IPL_SOFTSERIAL)) {
softint_deliver(ci, IPL_SOFTSERIAL);
continue;
}
KASSERT(old_ipl < IPL_SOFTNET);
if (softints & (1 << IPL_SOFTNET)) {
softint_deliver(ci, IPL_SOFTNET);
continue;
}
KASSERT(old_ipl < IPL_SOFTBIO);
if (softints & (1 << IPL_SOFTBIO)) {
softint_deliver(ci, IPL_SOFTBIO);
continue;
}
KASSERT(old_ipl < IPL_SOFTCLOCK);
if (softints & (1 << IPL_SOFTCLOCK)) {
softint_deliver(ci, IPL_SOFTCLOCK);
continue;
}
#ifdef __HAVE_PREEMPTION
KASSERT(old_ipl == IPL_NONE);
KASSERT(softints == (1 << IPL_NONE));
ci->ci_data.cpu_softints ^= (1 << IPL_NONE);
kpreempt(pc);
#endif
}
}
void
powerpc_softint_init_md(lwp_t *l, u_int si_level, uintptr_t *machdep_p)
{
struct cpu_info * const ci = l->l_cpu;
*machdep_p = 1 << SOFTINT2IPL(si_level);
KASSERT(*machdep_p & IPL_SOFTMASK);
ci->ci_softlwps[si_level] = l;
}
void
powerpc_softint_trigger(uintptr_t machdep)
{
struct cpu_info * const ci = curcpu();
atomic_or_uint(&ci->ci_data.cpu_softints, machdep);
}
#endif