Module Name: src Committed By: skrll Date: Thu Apr 5 16:13:47 UTC 2012
Added Files: src/sys/arch/hppa/hppa: ipifuncs.c Log Message: Commit work in progress ipi functions. To generate a diff of this commit: cvs rdiff -u -r0 -r1.1 src/sys/arch/hppa/hppa/ipifuncs.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Added files: Index: src/sys/arch/hppa/hppa/ipifuncs.c diff -u /dev/null src/sys/arch/hppa/hppa/ipifuncs.c:1.1 --- /dev/null Thu Apr 5 16:13:47 2012 +++ src/sys/arch/hppa/hppa/ipifuncs.c Thu Apr 5 16:13:46 2012 @@ -0,0 +1,211 @@ +/* $NetBSD: ipifuncs.c,v 1.1 2012/04/05 16:13:46 skrll Exp $ */ +/* $OpenBSD: ipi.c,v 1.4 2011/01/14 13:20:06 jsing Exp $ */ + +/* + * Copyright (c) 2010 Joel Sing <js...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/systm.h> +#include <sys/mutex.h> +#include <sys/device.h> +#include <sys/atomic.h> +#include <sys/xcall.h> + +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#if 0 +#include <machine/fpu.h> +#endif +#include <machine/iomod.h> +#include <machine/intr.h> +#include <machine/mutex.h> +#include <machine/reg.h> +#include <machine/int_fmtio.h> + +#include <hppa/hppa/cpuvar.h> + +void hppa_ipi_nop(void); +void hppa_ipi_halt(void); +void hppa_ipi_xcall(void); + +void (*ipifunc[HPPA_NIPI])(void) = +{ + hppa_ipi_nop, + hppa_ipi_halt, + hppa_ipi_xcall +}; + +const char *ipinames[HPPA_NIPI] = { + "nop ipi", + "halt ipi", + "xcall ipi" +}; + +void +hppa_ipi_init(struct cpu_info *ci) +{ + struct cpu_softc *sc = ci->ci_softc; + int i; + + evcnt_attach_dynamic(&sc->sc_evcnt_ipi, EVCNT_TYPE_INTR, + NULL, device_xname(sc->sc_dev), "ipi"); + + for (i = 0; i < HPPA_NIPI; i++) { + evcnt_attach_dynamic(&sc->sc_evcnt_which_ipi[i], + EVCNT_TYPE_INTR, NULL, device_xname(sc->sc_dev), + ipinames[i]); + } +} + +int +hppa_ipi_intr(void *arg) +{ + struct cpu_info *ci = curcpu(); + struct cpu_softc *sc = ci->ci_softc; + u_long ipi_pending; + int bit = 0; + +printf_nolog("%s: ci %p\n",__func__, curcpu()); + + /* Handle an IPI. */ + ipi_pending = atomic_swap_ulong(&ci->ci_ipi, 0); + + KASSERT(ipi_pending); + + sc->sc_evcnt_ipi.ev_count++; + + while (ipi_pending) { + if (ipi_pending & (1L << bit)) { + sc->sc_evcnt_which_ipi[bit].ev_count++; + (*ipifunc[bit])(); + } + ipi_pending &= ~(1L << bit); + bit++; + } + + return 1; +} + +int +hppa_ipi_send(struct cpu_info *ci, u_long ipi) +{ + struct iomod *cpu; +printf_nolog("%s: made it\n", __func__); + KASSERT(ci->ci_flags & CPUF_RUNNING); + + atomic_or_ulong(&ci->ci_ipi, (1L << ipi)); +printf_nolog("%s: after atomic\n",__func__); + + /* Send an IPI to the specified CPU by triggering EIR{1} (irq 30). */ + cpu = (struct iomod *)(ci->ci_hpa); + cpu->io_eir = 1; + membar_sync(); +printf_nolog("%s: after io_eir ci %p\n",__func__, curcpu()); + + return 0; +} + +int +hppa_ipi_broadcast(u_long ipi) +{ + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + int count = 0; + + for (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) +{ + struct cpu_info *ci = curcpu(); + + /* Turn off interrupts and halt CPU. */ +// hppa_intr_disable(); + ci->ci_flags &= ~CPUF_RUNNING; + + for (;;) + ; +} + +#if 0 +void +hppa_ipi_fpu_save(void) +{ + fpu_cpu_save(1); +} + +void +hppa_ipi_fpu_flush(void) +{ + fpu_cpu_save(0); +} + +#endif + +void +hppa_ipi_xcall(void) +{ + + xc_ipi_handler(); +} + +void +xc_send_ipi(struct cpu_info *ci) +{ + + KASSERT(kpreempt_disabled()); + KASSERT(curcpu() != ci); +Debugger(); + if (ci) { + /* Unicast: remote CPU. */ + hppa_ipi_send(ci, HPPA_IPI_XCALL); + } else { + /* Broadcast: all, but local CPU (caller will handle it). */ + hppa_ipi_broadcast(HPPA_IPI_XCALL); + } +} + +void hppa_ipi_counts(void); +void +hppa_ipi_counts(void) +{ + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + struct cpu_softc *sc; + + for (CPU_INFO_FOREACH(cii, ci)) { + if ((ci->ci_flags & CPUF_RUNNING)) { + sc = ci->ci_softc; + printf("%s: ci %p cpuid %d total ipis %" PRIu64 "\n", __func__, ci, ci->ci_cpuid, sc->sc_evcnt_ipi.ev_count); + printf("%s: ci %p cpuid %d ipis bit 0 %" PRIu64 "\n", __func__, ci, ci->ci_cpuid, sc->sc_evcnt_which_ipi[0].ev_count); + printf("%s: ci %p cpuid %d ipis bit 1 %" PRIu64 "\n", __func__, ci, ci->ci_cpuid, sc->sc_evcnt_which_ipi[1].ev_count); + printf("%s: ci %p cpuid %d ipis bit 2 %" PRIu64 "\n", __func__, ci, ci->ci_cpuid, sc->sc_evcnt_which_ipi[2].ev_count); + } + } +}