smp.h revision 135943
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 135943 2004-09-29 21:39:36Z kensmith $
27 */
28
29#ifndef	_MACHINE_SMP_H_
30#define	_MACHINE_SMP_H_
31
32#define	CPU_CLKSYNC		1
33#define	CPU_INIT		2
34#define	CPU_BOOTSTRAP		3
35
36#ifndef	LOCORE
37
38#include <machine/intr_machdep.h>
39#include <machine/tte.h>
40
41#define	IDR_BUSY	(1<<0)
42#define	IDR_NACK	(1<<1)
43
44#define	IPI_AST		PIL_AST
45#define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
46#define	IPI_STOP	PIL_STOP
47
48#define	IPI_RETRIES	5000
49
50struct cpu_start_args {
51	u_int	csa_count;
52	u_int	csa_mid;
53	u_int	csa_state;
54	vm_offset_t csa_pcpu;
55	u_long	csa_tick;
56	u_long	csa_ver;
57	struct	tte csa_ttes[PCPU_PAGES];
58};
59
60struct ipi_cache_args {
61	u_int	ica_mask;
62	vm_paddr_t ica_pa;
63};
64
65struct ipi_tlb_args {
66	u_int	ita_mask;
67	struct	pmap *ita_pmap;
68	u_long	ita_start;
69	u_long	ita_end;
70};
71#define	ita_va	ita_start
72
73struct pcpu;
74
75void	cpu_mp_bootstrap(struct pcpu *pc);
76void	cpu_mp_shutdown(void);
77
78void	cpu_ipi_selected(u_int cpus, u_long d0, u_long d1, u_long d2);
79void	cpu_ipi_send(u_int mid, u_long d0, u_long d1, u_long d2);
80
81void	ipi_selected(u_int cpus, u_int ipi);
82void	ipi_all(u_int ipi);
83void	ipi_all_but_self(u_int ipi);
84
85vm_offset_t mp_tramp_alloc(void);
86
87extern	struct mtx ipi_mtx;
88extern	struct ipi_cache_args ipi_cache_args;
89extern	struct ipi_tlb_args ipi_tlb_args;
90
91extern	vm_offset_t mp_tramp;
92extern	char *mp_tramp_code;
93extern	u_long mp_tramp_code_len;
94extern	u_long mp_tramp_tlb_slots;
95extern	u_long mp_tramp_func;
96
97extern	void mp_startup(void);
98
99extern	char tl_ipi_cheetah_dcache_page_inval[];
100extern	char tl_ipi_spitfire_dcache_page_inval[];
101extern	char tl_ipi_spitfire_icache_page_inval[];
102
103extern	char tl_ipi_level[];
104extern	char tl_ipi_tlb_context_demap[];
105extern	char tl_ipi_tlb_page_demap[];
106extern	char tl_ipi_tlb_range_demap[];
107
108#ifdef SMP
109
110#if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_)
111
112static __inline void *
113ipi_dcache_page_inval(void *func, vm_paddr_t pa)
114{
115	struct ipi_cache_args *ica;
116
117	if (smp_cpus == 1)
118		return (NULL);
119	ica = &ipi_cache_args;
120	mtx_lock_spin(&ipi_mtx);
121	ica->ica_mask = all_cpus;
122	ica->ica_pa = pa;
123	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
124	return (&ica->ica_mask);
125}
126
127static __inline void *
128ipi_icache_page_inval(void *func, vm_paddr_t pa)
129{
130	struct ipi_cache_args *ica;
131
132	if (smp_cpus == 1)
133		return (NULL);
134	ica = &ipi_cache_args;
135	mtx_lock_spin(&ipi_mtx);
136	ica->ica_mask = all_cpus;
137	ica->ica_pa = pa;
138	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
139	return (&ica->ica_mask);
140}
141
142static __inline void *
143ipi_tlb_context_demap(struct pmap *pm)
144{
145	struct ipi_tlb_args *ita;
146	u_int cpus;
147
148	if (smp_cpus == 1)
149		return (NULL);
150	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
151		return (NULL);
152	ita = &ipi_tlb_args;
153	mtx_lock_spin(&ipi_mtx);
154	ita->ita_mask = cpus | PCPU_GET(cpumask);
155	ita->ita_pmap = pm;
156	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
157	    (u_long)ita);
158	return (&ita->ita_mask);
159}
160
161static __inline void *
162ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
163{
164	struct ipi_tlb_args *ita;
165	u_int cpus;
166
167	if (smp_cpus == 1)
168		return (NULL);
169	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
170		return (NULL);
171	ita = &ipi_tlb_args;
172	mtx_lock_spin(&ipi_mtx);
173	ita->ita_mask = cpus | PCPU_GET(cpumask);
174	ita->ita_pmap = pm;
175	ita->ita_va = va;
176	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
177	return (&ita->ita_mask);
178}
179
180static __inline void *
181ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
182{
183	struct ipi_tlb_args *ita;
184	u_int cpus;
185
186	if (smp_cpus == 1)
187		return (NULL);
188	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
189		return (NULL);
190	ita = &ipi_tlb_args;
191	mtx_lock_spin(&ipi_mtx);
192	ita->ita_mask = cpus | PCPU_GET(cpumask);
193	ita->ita_pmap = pm;
194	ita->ita_start = start;
195	ita->ita_end = end;
196	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap, (u_long)ita);
197	return (&ita->ita_mask);
198}
199
200static __inline void
201ipi_wait(void *cookie)
202{
203	u_int *volatile mask;
204
205	if ((mask = cookie) != NULL) {
206		atomic_clear_int(mask, PCPU_GET(cpumask));
207		while (*mask != 0)
208			;
209		mtx_unlock_spin(&ipi_mtx);
210	}
211}
212
213#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
214
215#else
216
217static __inline void *
218ipi_dcache_page_inval(void *func, vm_paddr_t pa)
219{
220	return (NULL);
221}
222
223static __inline void *
224ipi_icache_page_inval(void *func, vm_paddr_t pa)
225{
226	return (NULL);
227}
228
229static __inline void *
230ipi_tlb_context_demap(struct pmap *pm)
231{
232	return (NULL);
233}
234
235static __inline void *
236ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
237{
238	return (NULL);
239}
240
241static __inline void *
242ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
243{
244	return (NULL);
245}
246
247static __inline void
248ipi_wait(void *cookie)
249{
250}
251
252#endif /* SMP */
253
254#endif /* !LOCORE */
255
256#endif /* !_MACHINE_SMP_H_ */
257