#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mutex.h>
#include <machine/cpu.h>
#include <machine/cpufunc.h>
#include <machine/fpu.h>
#include <machine/iomod.h>
#include <machine/intr.h>
#include <machine/mutex.h>
#include <machine/reg.h>
void hppa_ipi_nop(void);
void hppa_ipi_halt(void);
void hppa_ipi_fpu_save(void);
void hppa_ipi_fpu_flush(void);
void (*ipifunc[HPPA_NIPI])(void) =
{
hppa_ipi_nop,
hppa_ipi_halt,
hppa_ipi_fpu_save,
hppa_ipi_fpu_flush
};
void
hppa_ipi_init(struct cpu_info *ci)
{
mtx_init(&ci->ci_ipi_mtx, IPL_IPI);
ci->ci_mask |= (1 << 30);
}
int
hppa_ipi_intr(void *arg)
{
struct cpu_info *ci = curcpu();
u_long ipi_pending;
int bit = 0;
mtx_enter(&ci->ci_ipi_mtx);
ipi_pending = ci->ci_ipi;
ci->ci_ipi = 0;
mtx_leave(&ci->ci_ipi_mtx);
while (ipi_pending) {
if (ipi_pending & (1L << bit))
(*ipifunc[bit])();
ipi_pending &= ~(1L << bit);
bit++;
}
return 1;
}
int
hppa_ipi_send(struct cpu_info *ci, u_long ipi)
{
struct iomod *cpu;
if (!(ci->ci_flags & CPUF_RUNNING))
return -1;
mtx_enter(&ci->ci_ipi_mtx);
ci->ci_ipi |= (1L << ipi);
asm volatile ("sync" ::: "memory");
mtx_leave(&ci->ci_ipi_mtx);
cpu = (struct iomod *)(ci->ci_hpa);
cpu->io_eir = 1;
asm volatile ("sync" ::: "memory");
return 0;
}
int
hppa_ipi_broadcast(u_long ipi)
{
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
int count = 0;
CPU_INFO_FOREACH(cii, ci)
if (ci != curcpu() && (ci->ci_flags & CPUF_RUNNING))
if (hppa_ipi_send(ci, ipi))
count++;
return count;
}
void
hppa_ipi_nop(void)
{
}
void
hppa_ipi_halt(void)
{
SCHED_ASSERT_UNLOCKED();
hppa_intr_disable();
curcpu()->ci_flags &= ~CPUF_RUNNING;
for (;;) ;
}
void
hppa_ipi_fpu_save(void)
{
fpu_cpu_save(1);
}
void
hppa_ipi_fpu_flush(void)
{
fpu_cpu_save(0);
}