xref: /openbsd-src/sys/arch/hppa/hppa/ipi.c (revision b27348b2082c02cb5227e0e4933400ad6739ec5a)
1 /*	$OpenBSD: ipi.c,v 1.5 2017/09/08 05:36:51 deraadt Exp $	*/
2 
3 /*
4  * Copyright (c) 2010 Joel Sing <jsing@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/mutex.h>
22 
23 #include <machine/cpu.h>
24 #include <machine/cpufunc.h>
25 #include <machine/fpu.h>
26 #include <machine/iomod.h>
27 #include <machine/intr.h>
28 #include <machine/mutex.h>
29 #include <machine/reg.h>
30 
31 void hppa_ipi_nop(void);
32 void hppa_ipi_halt(void);
33 void hppa_ipi_fpu_save(void);
34 void hppa_ipi_fpu_flush(void);
35 
36 void (*ipifunc[HPPA_NIPI])(void) =
37 {
38 	hppa_ipi_nop,
39 	hppa_ipi_halt,
40 	hppa_ipi_fpu_save,
41 	hppa_ipi_fpu_flush
42 };
43 
44 void
hppa_ipi_init(struct cpu_info * ci)45 hppa_ipi_init(struct cpu_info *ci)
46 {
47 	/* Initialise IPIs for given CPU. */
48 	mtx_init(&ci->ci_ipi_mtx, IPL_IPI);
49 	ci->ci_mask |= (1 << 30);
50 }
51 
52 int
hppa_ipi_intr(void * arg)53 hppa_ipi_intr(void *arg)
54 {
55 	struct cpu_info *ci = curcpu();
56 	u_long ipi_pending;
57 	int bit = 0;
58 
59 	/* Handle an IPI. */
60 	mtx_enter(&ci->ci_ipi_mtx);
61 	ipi_pending = ci->ci_ipi;
62 	ci->ci_ipi = 0;
63 	mtx_leave(&ci->ci_ipi_mtx);
64 
65 	while (ipi_pending) {
66 		if (ipi_pending & (1L << bit))
67 			(*ipifunc[bit])();
68 		ipi_pending &= ~(1L << bit);
69 		bit++;
70 	}
71 
72 	return 1;
73 }
74 
75 int
hppa_ipi_send(struct cpu_info * ci,u_long ipi)76 hppa_ipi_send(struct cpu_info *ci, u_long ipi)
77 {
78 	struct iomod *cpu;
79 
80 	if (!(ci->ci_flags & CPUF_RUNNING))
81 		return -1;
82 
83 	mtx_enter(&ci->ci_ipi_mtx);
84 	ci->ci_ipi |= (1L << ipi);
85 	asm volatile ("sync" ::: "memory");
86 	mtx_leave(&ci->ci_ipi_mtx);
87 
88 	/* Send an IPI to the specified CPU by triggering EIR{1} (irq 30). */
89 	cpu = (struct iomod *)(ci->ci_hpa);
90 	cpu->io_eir = 1;
91 	asm volatile ("sync" ::: "memory");
92 
93 	return 0;
94 }
95 
96 int
hppa_ipi_broadcast(u_long ipi)97 hppa_ipi_broadcast(u_long ipi)
98 {
99 	CPU_INFO_ITERATOR cii;
100 	struct cpu_info *ci;
101 	int count = 0;
102 
103 	CPU_INFO_FOREACH(cii, ci)
104 		if (ci != curcpu() && (ci->ci_flags & CPUF_RUNNING))
105 			if (hppa_ipi_send(ci, ipi))
106 				count++;
107 
108 	return count;
109 }
110 
111 void
hppa_ipi_nop(void)112 hppa_ipi_nop(void)
113 {
114 }
115 
116 void
hppa_ipi_halt(void)117 hppa_ipi_halt(void)
118 {
119 	/* Turn off interrupts and halt CPU. */
120 	SCHED_ASSERT_UNLOCKED();
121 	hppa_intr_disable();
122 	curcpu()->ci_flags &= ~CPUF_RUNNING;
123 
124 	for (;;) ;
125 }
126 
127 void
hppa_ipi_fpu_save(void)128 hppa_ipi_fpu_save(void)
129 {
130 	fpu_cpu_save(1);
131 }
132 
133 void
hppa_ipi_fpu_flush(void)134 hppa_ipi_fpu_flush(void)
135 {
136 	fpu_cpu_save(0);
137 }
138