smp.h revision 196196
1/*-
2 * Copyright (c) 2001 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/sparc64/include/smp.h 196196 2009-08-13 17:09:45Z attilio $
27 */
28
29#ifndef	_MACHINE_SMP_H_
30#define	_MACHINE_SMP_H_
31
32#ifdef SMP
33
34#define	CPU_TICKSYNC		1
35#define	CPU_STICKSYNC		2
36#define	CPU_INIT		3
37#define	CPU_BOOTSTRAP		4
38
39#ifndef	LOCORE
40
41#include <machine/intr_machdep.h>
42#include <machine/pcb.h>
43#include <machine/tte.h>
44
45#define	IDR_BUSY			0x0000000000000001ULL
46#define	IDR_NACK			0x0000000000000002ULL
47#define	IDR_CHEETAH_ALL_BUSY		0x5555555555555555ULL
48#define	IDR_CHEETAH_ALL_NACK		(~IDR_CHEETAH_ALL_BUSY)
49#define	IDR_CHEETAH_MAX_BN_PAIRS	32
50#define	IDR_JALAPENO_MAX_BN_PAIRS	4
51
52#define	IDC_ITID_SHIFT			14
53#define	IDC_BN_SHIFT			24
54
55#define	IPI_AST		PIL_AST
56#define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
57#define	IPI_PREEMPT	PIL_PREEMPT
58#define	IPI_STOP	PIL_STOP
59#define	IPI_STOP_HARD	PIL_STOP
60
61#define	IPI_RETRIES	5000
62
63struct cpu_start_args {
64	u_int	csa_count;
65	u_int	csa_mid;
66	u_int	csa_state;
67	vm_offset_t csa_pcpu;
68	u_long	csa_tick;
69	u_long	csa_stick;
70	u_long	csa_ver;
71	struct	tte csa_ttes[PCPU_PAGES];
72};
73
74struct ipi_cache_args {
75	u_int	ica_mask;
76	vm_paddr_t ica_pa;
77};
78
79struct ipi_tlb_args {
80	u_int	ita_mask;
81	struct	pmap *ita_pmap;
82	u_long	ita_start;
83	u_long	ita_end;
84};
85#define	ita_va	ita_start
86
87struct pcpu;
88
89extern struct pcb stoppcbs[];
90
91void	cpu_mp_bootstrap(struct pcpu *pc);
92void	cpu_mp_shutdown(void);
93
94typedef	void cpu_ipi_selected_t(u_int, u_long, u_long, u_long);
95extern	cpu_ipi_selected_t *cpu_ipi_selected;
96
97void	mp_init(void);
98
99extern	struct mtx ipi_mtx;
100extern	struct ipi_cache_args ipi_cache_args;
101extern	struct ipi_tlb_args ipi_tlb_args;
102
103extern	char *mp_tramp_code;
104extern	u_long mp_tramp_code_len;
105extern	u_long mp_tramp_tlb_slots;
106extern	u_long mp_tramp_func;
107
108extern	void mp_startup(void);
109
110extern	char tl_ipi_cheetah_dcache_page_inval[];
111extern	char tl_ipi_spitfire_dcache_page_inval[];
112extern	char tl_ipi_spitfire_icache_page_inval[];
113
114extern	char tl_ipi_level[];
115extern	char tl_ipi_tlb_context_demap[];
116extern	char tl_ipi_tlb_page_demap[];
117extern	char tl_ipi_tlb_range_demap[];
118
119static __inline void
120ipi_all_but_self(u_int ipi)
121{
122
123	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)tl_ipi_level, ipi);
124}
125
126static __inline void
127ipi_selected(u_int cpus, u_int ipi)
128{
129
130	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
131}
132
133#if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_)
134
135static __inline void *
136ipi_dcache_page_inval(void *func, vm_paddr_t pa)
137{
138	struct ipi_cache_args *ica;
139
140	if (smp_cpus == 1)
141		return (NULL);
142	ica = &ipi_cache_args;
143	mtx_lock_spin(&ipi_mtx);
144	ica->ica_mask = all_cpus;
145	ica->ica_pa = pa;
146	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
147	return (&ica->ica_mask);
148}
149
150static __inline void *
151ipi_icache_page_inval(void *func, vm_paddr_t pa)
152{
153	struct ipi_cache_args *ica;
154
155	if (smp_cpus == 1)
156		return (NULL);
157	ica = &ipi_cache_args;
158	mtx_lock_spin(&ipi_mtx);
159	ica->ica_mask = all_cpus;
160	ica->ica_pa = pa;
161	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
162	return (&ica->ica_mask);
163}
164
165static __inline void *
166ipi_tlb_context_demap(struct pmap *pm)
167{
168	struct ipi_tlb_args *ita;
169	u_int cpus;
170
171	if (smp_cpus == 1)
172		return (NULL);
173	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
174		return (NULL);
175	ita = &ipi_tlb_args;
176	mtx_lock_spin(&ipi_mtx);
177	ita->ita_mask = cpus | PCPU_GET(cpumask);
178	ita->ita_pmap = pm;
179	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
180	    (u_long)ita);
181	return (&ita->ita_mask);
182}
183
184static __inline void *
185ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
186{
187	struct ipi_tlb_args *ita;
188	u_int cpus;
189
190	if (smp_cpus == 1)
191		return (NULL);
192	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
193		return (NULL);
194	ita = &ipi_tlb_args;
195	mtx_lock_spin(&ipi_mtx);
196	ita->ita_mask = cpus | PCPU_GET(cpumask);
197	ita->ita_pmap = pm;
198	ita->ita_va = va;
199	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
200	return (&ita->ita_mask);
201}
202
203static __inline void *
204ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
205{
206	struct ipi_tlb_args *ita;
207	u_int cpus;
208
209	if (smp_cpus == 1)
210		return (NULL);
211	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
212		return (NULL);
213	ita = &ipi_tlb_args;
214	mtx_lock_spin(&ipi_mtx);
215	ita->ita_mask = cpus | PCPU_GET(cpumask);
216	ita->ita_pmap = pm;
217	ita->ita_start = start;
218	ita->ita_end = end;
219	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap, (u_long)ita);
220	return (&ita->ita_mask);
221}
222
223static __inline void
224ipi_wait(void *cookie)
225{
226	volatile u_int *mask;
227
228	if ((mask = cookie) != NULL) {
229		atomic_clear_int(mask, PCPU_GET(cpumask));
230		while (*mask != 0)
231			;
232		mtx_unlock_spin(&ipi_mtx);
233	}
234}
235
236#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
237
238#endif /* !LOCORE */
239
240#else
241
242#ifndef	LOCORE
243
244static __inline void *
245ipi_dcache_page_inval(void *func, vm_paddr_t pa)
246{
247
248	return (NULL);
249}
250
251static __inline void *
252ipi_icache_page_inval(void *func, vm_paddr_t pa)
253{
254
255	return (NULL);
256}
257
258static __inline void *
259ipi_tlb_context_demap(struct pmap *pm)
260{
261
262	return (NULL);
263}
264
265static __inline void *
266ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
267{
268
269	return (NULL);
270}
271
272static __inline void *
273ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
274{
275
276	return (NULL);
277}
278
279static __inline void
280ipi_wait(void *cookie)
281{
282
283}
284
285static __inline void
286tl_ipi_cheetah_dcache_page_inval(void)
287{
288
289}
290
291static __inline void
292tl_ipi_spitfire_dcache_page_inval(void)
293{
294
295}
296
297static __inline void
298tl_ipi_spitfire_icache_page_inval(void)
299{
300
301}
302
303#endif /* !LOCORE */
304
305#endif /* SMP */
306
307#endif /* !_MACHINE_SMP_H_ */
308