smp.h revision 100718
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 100718 2002-07-26 15:54:04Z jake $
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	100
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	u_long	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	ipi_cache_args ipi_cache_args;
88extern	struct	ipi_level_args ipi_level_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_dcache_page_inval[];
100extern	char tl_ipi_icache_page_inval[];
101extern	char tl_ipi_level[];
102extern	char tl_ipi_tlb_context_demap[];
103extern	char tl_ipi_tlb_page_demap[];
104extern	char tl_ipi_tlb_range_demap[];
105
106#ifdef SMP
107
108static __inline void *
109ipi_dcache_page_inval(vm_offset_t pa)
110{
111	struct ipi_cache_args *ica;
112
113	if (smp_cpus == 1)
114		return (NULL);
115	ica = &ipi_cache_args;
116	ica->ica_mask = all_cpus;
117	ica->ica_pa = pa;
118	cpu_ipi_selected(PCPU_GET(other_cpus), 0,
119	    (u_long)tl_ipi_dcache_page_inval, (u_long)ica);
120	return (&ica->ica_mask);
121}
122
123static __inline void *
124ipi_icache_page_inval(vm_offset_t pa)
125{
126	struct ipi_cache_args *ica;
127
128	if (smp_cpus == 1)
129		return (NULL);
130	ica = &ipi_cache_args;
131	ica->ica_mask = all_cpus;
132	ica->ica_pa = pa;
133	cpu_ipi_selected(PCPU_GET(other_cpus), 0,
134	    (u_long)tl_ipi_icache_page_inval, (u_long)ica);
135	return (&ica->ica_mask);
136}
137
138#ifdef _MACHINE_PMAP_H_
139
140static __inline void *
141ipi_tlb_context_demap(struct pmap *pm)
142{
143	struct ipi_tlb_args *ita;
144	u_int cpus;
145
146	if (smp_cpus == 1)
147		return (NULL);
148	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
149		return (NULL);
150	ita = &ipi_tlb_args;
151	ita->ita_mask = cpus | PCPU_GET(cpumask);
152	ita->ita_pmap = pm;
153	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
154	    (u_long)ita);
155	return (&ita->ita_mask);
156}
157
158static __inline void *
159ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
160{
161	struct ipi_tlb_args *ita;
162	u_int cpus;
163
164	if (smp_cpus == 1)
165		return (NULL);
166	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
167		return (NULL);
168	ita = &ipi_tlb_args;
169	ita->ita_mask = cpus | PCPU_GET(cpumask);
170	ita->ita_pmap = pm;
171	ita->ita_va = va;
172	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
173	return (&ita->ita_mask);
174}
175
176static __inline void *
177ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
178{
179	struct ipi_tlb_args *ita;
180	u_int cpus;
181
182	if (smp_cpus == 1)
183		return (NULL);
184	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
185		return (NULL);
186	ita = &ipi_tlb_args;
187	ita->ita_mask = cpus | PCPU_GET(cpumask);
188	ita->ita_pmap = pm;
189	ita->ita_start = start;
190	ita->ita_end = end;
191	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap, (u_long)ita);
192	return (&ita->ita_mask);
193}
194
195static __inline void
196ipi_wait(void *cookie)
197{
198	u_int *volatile mask;
199
200	if ((mask = cookie) != NULL) {
201		atomic_clear_int(mask, PCPU_GET(cpumask));
202		while (*mask != 0)
203			;
204	}
205}
206
207#endif
208
209#else
210
211static __inline void *
212ipi_dcache_page_inval(vm_offset_t pa)
213{
214	return (NULL);
215}
216
217static __inline void *
218ipi_icache_page_inval(vm_offset_t pa)
219{
220	return (NULL);
221}
222
223static __inline void *
224ipi_tlb_context_demap(struct pmap *pm)
225{
226	return (NULL);
227}
228
229static __inline void *
230ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
231{
232	return (NULL);
233}
234
235static __inline void *
236ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
237{
238	return (NULL);
239}
240
241static __inline void
242ipi_wait(void *cookie)
243{
244}
245
246#endif /* SMP */
247
248#endif /* !LOCORE */
249
250#endif /* !_MACHINE_SMP_H_ */
251