smp.h revision 239864
180708Sjake/*-
280708Sjake * Copyright (c) 2001 Jake Burkholder.
3223126Smarius * Copyright (c) 2007 - 2011 Marius Strobl <marius@FreeBSD.org>
480708Sjake * All rights reserved.
580708Sjake *
680708Sjake * Redistribution and use in source and binary forms, with or without
780708Sjake * modification, are permitted provided that the following conditions
880708Sjake * are met:
980708Sjake * 1. Redistributions of source code must retain the above copyright
1080708Sjake *    notice, this list of conditions and the following disclaimer.
1180708Sjake * 2. Redistributions in binary form must reproduce the above copyright
1280708Sjake *    notice, this list of conditions and the following disclaimer in the
1380708Sjake *    documentation and/or other materials provided with the distribution.
1480708Sjake *
1581334Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1680708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1780708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1881334Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1980708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2080708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2180708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2280708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2380708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2480708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2580708Sjake * SUCH DAMAGE.
2680708Sjake *
2780708Sjake * $FreeBSD: head/sys/sparc64/include/smp.h 239864 2012-08-29 16:56:50Z marius $
2880708Sjake */
2980708Sjake
3080708Sjake#ifndef	_MACHINE_SMP_H_
3180708Sjake#define	_MACHINE_SMP_H_
3280708Sjake
33183142Smarius#ifdef SMP
34183142Smarius
35182730Smarius#define	CPU_TICKSYNC		1
36182730Smarius#define	CPU_STICKSYNC		2
37182730Smarius#define	CPU_INIT		3
38182730Smarius#define	CPU_BOOTSTRAP		4
3989051Sjake
4089051Sjake#ifndef	LOCORE
4189051Sjake
42222813Sattilio#include <sys/cpuset.h>
43209695Smarius#include <sys/proc.h>
44209695Smarius#include <sys/sched.h>
45209695Smarius
4691157Sjake#include <machine/intr_machdep.h>
47169730Skan#include <machine/pcb.h>
4891617Sjake#include <machine/tte.h>
4991157Sjake
50170846Smarius#define	IDR_BUSY			0x0000000000000001ULL
51170846Smarius#define	IDR_NACK			0x0000000000000002ULL
52170846Smarius#define	IDR_CHEETAH_ALL_BUSY		0x5555555555555555ULL
53170846Smarius#define	IDR_CHEETAH_ALL_NACK		(~IDR_CHEETAH_ALL_BUSY)
54170846Smarius#define	IDR_CHEETAH_MAX_BN_PAIRS	32
55170846Smarius#define	IDR_JALAPENO_MAX_BN_PAIRS	4
5689051Sjake
57169796Smarius#define	IDC_ITID_SHIFT			14
58170846Smarius#define	IDC_BN_SHIFT			24
59169796Smarius
6089051Sjake#define	IPI_AST		PIL_AST
6189051Sjake#define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
62178048Smarius#define	IPI_PREEMPT	PIL_PREEMPT
63210601Smav#define	IPI_HARDCLOCK	PIL_HARDCLOCK
6489051Sjake#define	IPI_STOP	PIL_STOP
65196196Sattilio#define	IPI_STOP_HARD	PIL_STOP
6689051Sjake
67135943Skensmith#define	IPI_RETRIES	5000
6889051Sjake
6989051Sjakestruct cpu_start_args {
7091783Sjake	u_int	csa_count;
7189051Sjake	u_int	csa_mid;
7289051Sjake	u_int	csa_state;
7391783Sjake	vm_offset_t csa_pcpu;
7491617Sjake	u_long	csa_tick;
75182730Smarius	u_long	csa_stick;
7691617Sjake	u_long	csa_ver;
7791617Sjake	struct	tte csa_ttes[PCPU_PAGES];
7889051Sjake};
7989051Sjake
8097001Sjakestruct ipi_cache_args {
81222813Sattilio	cpuset_t ica_mask;
82113238Sjake	vm_paddr_t ica_pa;
8397001Sjake};
8497001Sjake
85211071Smariusstruct ipi_rd_args {
86222813Sattilio	cpuset_t ira_mask;
87211071Smarius	register_t *ira_val;
88211071Smarius};
89211071Smarius
9089051Sjakestruct ipi_tlb_args {
91222813Sattilio	cpuset_t ita_mask;
9291783Sjake	struct	pmap *ita_pmap;
9389051Sjake	u_long	ita_start;
9489051Sjake	u_long	ita_end;
9589051Sjake};
9689051Sjake#define	ita_va	ita_start
9789051Sjake
9889051Sjakestruct pcpu;
9989051Sjake
100152022Sjhbextern struct pcb stoppcbs[];
101152022Sjhb
10289051Sjakevoid	cpu_mp_bootstrap(struct pcpu *pc);
10392199Sjakevoid	cpu_mp_shutdown(void);
10489051Sjake
105222813Sattiliotypedef	void cpu_ipi_selected_t(cpuset_t, u_long, u_long, u_long);
106170846Smariusextern	cpu_ipi_selected_t *cpu_ipi_selected;
107211050Smariustypedef	void cpu_ipi_single_t(u_int, u_long, u_long, u_long);
108211050Smariusextern	cpu_ipi_single_t *cpu_ipi_single;
10989051Sjake
110204152Smariusvoid	mp_init(u_int cpu_impl);
11191617Sjake
112108187Sjakeextern	struct ipi_cache_args ipi_cache_args;
113211071Smariusextern	struct ipi_rd_args ipi_rd_args;
114108187Sjakeextern	struct ipi_tlb_args ipi_tlb_args;
11589051Sjake
11691617Sjakeextern	char *mp_tramp_code;
11791617Sjakeextern	u_long mp_tramp_code_len;
11891617Sjakeextern	u_long mp_tramp_tlb_slots;
11991617Sjakeextern	u_long mp_tramp_func;
12091617Sjake
12191617Sjakeextern	void mp_startup(void);
12291617Sjake
123112399Sjakeextern	char tl_ipi_cheetah_dcache_page_inval[];
124112399Sjakeextern	char tl_ipi_spitfire_dcache_page_inval[];
125112399Sjakeextern	char tl_ipi_spitfire_icache_page_inval[];
126112399Sjake
12789051Sjakeextern	char tl_ipi_level[];
128211071Smarius
129211071Smariusextern	char tl_ipi_stick_rd[];
130211071Smariusextern	char tl_ipi_tick_rd[];
131211071Smarius
13289051Sjakeextern	char tl_ipi_tlb_context_demap[];
13389051Sjakeextern	char tl_ipi_tlb_page_demap[];
13489051Sjakeextern	char tl_ipi_tlb_range_demap[];
13589051Sjake
136183142Smariusstatic __inline void
137183142Smariusipi_all_but_self(u_int ipi)
138183142Smarius{
139223126Smarius	cpuset_t cpus;
14089051Sjake
141223126Smarius	cpus = all_cpus;
142223126Smarius	CPU_CLR(PCPU_GET(cpuid), &cpus);
143223126Smarius	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
144183142Smarius}
145183142Smarius
146183142Smariusstatic __inline void
147222813Sattilioipi_selected(cpuset_t cpus, u_int ipi)
148183142Smarius{
149183142Smarius
150183142Smarius	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
151183142Smarius}
152183142Smarius
153210939Sjhbstatic __inline void
154210939Sjhbipi_cpu(int cpu, u_int ipi)
155210939Sjhb{
156210939Sjhb
157211050Smarius	cpu_ipi_single(cpu, 0, (u_long)tl_ipi_level, ipi);
158210939Sjhb}
159210939Sjhb
160108187Sjake#if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_)
161108187Sjake
16297001Sjakestatic __inline void *
163113238Sjakeipi_dcache_page_inval(void *func, vm_paddr_t pa)
16497001Sjake{
16597001Sjake	struct ipi_cache_args *ica;
16697001Sjake
16797001Sjake	if (smp_cpus == 1)
16897001Sjake		return (NULL);
169209695Smarius	sched_pin();
17097001Sjake	ica = &ipi_cache_args;
171239864Smarius	mtx_lock_spin(&smp_ipi_mtx);
17297001Sjake	ica->ica_mask = all_cpus;
173223126Smarius	CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask);
17497001Sjake	ica->ica_pa = pa;
175223126Smarius	cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica);
17697001Sjake	return (&ica->ica_mask);
17797001Sjake}
17897001Sjake
17997001Sjakestatic __inline void *
180113238Sjakeipi_icache_page_inval(void *func, vm_paddr_t pa)
18197001Sjake{
18297001Sjake	struct ipi_cache_args *ica;
18397001Sjake
18497001Sjake	if (smp_cpus == 1)
18597001Sjake		return (NULL);
186209695Smarius	sched_pin();
18797001Sjake	ica = &ipi_cache_args;
188239864Smarius	mtx_lock_spin(&smp_ipi_mtx);
18997001Sjake	ica->ica_mask = all_cpus;
190223126Smarius	CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask);
19197001Sjake	ica->ica_pa = pa;
192223126Smarius	cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica);
19397001Sjake	return (&ica->ica_mask);
19497001Sjake}
19597001Sjake
19689051Sjakestatic __inline void *
197211071Smariusipi_rd(u_int cpu, void *func, u_long *val)
198211071Smarius{
199211071Smarius	struct ipi_rd_args *ira;
200211071Smarius
201211071Smarius	if (smp_cpus == 1)
202211071Smarius		return (NULL);
203211071Smarius	sched_pin();
204211071Smarius	ira = &ipi_rd_args;
205223126Smarius	CPU_SETOF(cpu, &ira->ira_mask);
206211071Smarius	ira->ira_val = val;
207211071Smarius	cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira);
208211071Smarius	return (&ira->ira_mask);
209211071Smarius}
210211071Smarius
211211071Smariusstatic __inline void *
21291783Sjakeipi_tlb_context_demap(struct pmap *pm)
21389051Sjake{
21489051Sjake	struct ipi_tlb_args *ita;
215222813Sattilio	cpuset_t cpus;
21689051Sjake
21791783Sjake	if (smp_cpus == 1)
21889051Sjake		return (NULL);
219209695Smarius	sched_pin();
220222813Sattilio	cpus = pm->pm_active;
221223126Smarius	CPU_AND(&cpus, &all_cpus);
222223126Smarius	CPU_CLR(PCPU_GET(cpuid), &cpus);
223222813Sattilio	if (CPU_EMPTY(&cpus)) {
224209695Smarius		sched_unpin();
22591783Sjake		return (NULL);
226209695Smarius	}
22789051Sjake	ita = &ipi_tlb_args;
228239864Smarius	mtx_lock_spin(&smp_ipi_mtx);
229222813Sattilio	ita->ita_mask = cpus;
23091783Sjake	ita->ita_pmap = pm;
23191783Sjake	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
23291783Sjake	    (u_long)ita);
23392199Sjake	return (&ita->ita_mask);
23489051Sjake}
23589051Sjake
23689051Sjakestatic __inline void *
237100718Sjakeipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
23889051Sjake{
23989051Sjake	struct ipi_tlb_args *ita;
240222813Sattilio	cpuset_t cpus;
24189051Sjake
24291783Sjake	if (smp_cpus == 1)
24389051Sjake		return (NULL);
244209695Smarius	sched_pin();
245222813Sattilio	cpus = pm->pm_active;
246223126Smarius	CPU_AND(&cpus, &all_cpus);
247223126Smarius	CPU_CLR(PCPU_GET(cpuid), &cpus);
248222813Sattilio	if (CPU_EMPTY(&cpus)) {
249209695Smarius		sched_unpin();
25091783Sjake		return (NULL);
251209695Smarius	}
25289051Sjake	ita = &ipi_tlb_args;
253239864Smarius	mtx_lock_spin(&smp_ipi_mtx);
254222813Sattilio	ita->ita_mask = cpus;
25591783Sjake	ita->ita_pmap = pm;
25689051Sjake	ita->ita_va = va;
25791783Sjake	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
25892199Sjake	return (&ita->ita_mask);
25989051Sjake}
26089051Sjake
26189051Sjakestatic __inline void *
26291783Sjakeipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
26389051Sjake{
26489051Sjake	struct ipi_tlb_args *ita;
265222813Sattilio	cpuset_t cpus;
26689051Sjake
26791783Sjake	if (smp_cpus == 1)
26889051Sjake		return (NULL);
269209695Smarius	sched_pin();
270222813Sattilio	cpus = pm->pm_active;
271223126Smarius	CPU_AND(&cpus, &all_cpus);
272223126Smarius	CPU_CLR(PCPU_GET(cpuid), &cpus);
273222813Sattilio	if (CPU_EMPTY(&cpus)) {
274209695Smarius		sched_unpin();
27591783Sjake		return (NULL);
276209695Smarius	}
27789051Sjake	ita = &ipi_tlb_args;
278239864Smarius	mtx_lock_spin(&smp_ipi_mtx);
279222813Sattilio	ita->ita_mask = cpus;
28091783Sjake	ita->ita_pmap = pm;
28189051Sjake	ita->ita_start = start;
28289051Sjake	ita->ita_end = end;
283211050Smarius	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap,
284211050Smarius	    (u_long)ita);
28592199Sjake	return (&ita->ita_mask);
28689051Sjake}
28789051Sjake
28889051Sjakestatic __inline void
28989051Sjakeipi_wait(void *cookie)
29089051Sjake{
291222813Sattilio	volatile cpuset_t *mask;
29289051Sjake
29392199Sjake	if ((mask = cookie) != NULL) {
294222813Sattilio		while (!CPU_EMPTY(mask))
29591617Sjake			;
296239864Smarius		mtx_unlock_spin(&smp_ipi_mtx);
297209695Smarius		sched_unpin();
29889051Sjake	}
29989051Sjake}
30089051Sjake
301239864Smariusstatic __inline void
302239864Smariusipi_wait_unlocked(void *cookie)
303239864Smarius{
304239864Smarius	volatile cpuset_t *mask;
305239864Smarius
306239864Smarius	if ((mask = cookie) != NULL) {
307239864Smarius		while (!CPU_EMPTY(mask))
308239864Smarius			;
309239864Smarius		sched_unpin();
310239864Smarius	}
311239864Smarius}
312239864Smarius
313108187Sjake#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
31491783Sjake
315183142Smarius#endif /* !LOCORE */
316183142Smarius
31789051Sjake#else
31889051Sjake
319183142Smarius#ifndef	LOCORE
320183142Smarius
32189051Sjakestatic __inline void *
322209695Smariusipi_dcache_page_inval(void *func __unused, vm_paddr_t pa __unused)
32397001Sjake{
324169796Smarius
32597001Sjake	return (NULL);
32697001Sjake}
32797001Sjake
32897001Sjakestatic __inline void *
329209695Smariusipi_icache_page_inval(void *func __unused, vm_paddr_t pa __unused)
33097001Sjake{
331169796Smarius
33297001Sjake	return (NULL);
33397001Sjake}
33497001Sjake
33597001Sjakestatic __inline void *
336211071Smariusipi_rd(u_int cpu __unused, void *func __unused, u_long *val __unused)
337211071Smarius{
338211071Smarius
339211071Smarius	return (NULL);
340211071Smarius}
341211071Smarius
342211071Smariusstatic __inline void *
343209695Smariusipi_tlb_context_demap(struct pmap *pm __unused)
34489051Sjake{
345169796Smarius
34689051Sjake	return (NULL);
34789051Sjake}
34889051Sjake
34989051Sjakestatic __inline void *
350209695Smariusipi_tlb_page_demap(struct pmap *pm __unused, vm_offset_t va __unused)
35189051Sjake{
352169796Smarius
35389051Sjake	return (NULL);
35489051Sjake}
35589051Sjake
35689051Sjakestatic __inline void *
357209695Smariusipi_tlb_range_demap(struct pmap *pm __unused, vm_offset_t start __unused,
358209695Smarius    __unused vm_offset_t end)
35989051Sjake{
360169796Smarius
36189051Sjake	return (NULL);
36289051Sjake}
36389051Sjake
36489051Sjakestatic __inline void
365239864Smariusipi_wait(void *cookie __unused)
36689051Sjake{
367169796Smarius
36889051Sjake}
36989051Sjake
370183142Smariusstatic __inline void
371239864Smariusipi_wait_unlocked(void *cookie __unused)
372239864Smarius{
373239864Smarius
374239864Smarius}
375239864Smarius
376239864Smariusstatic __inline void
377183142Smariustl_ipi_cheetah_dcache_page_inval(void)
378183142Smarius{
37989051Sjake
380183142Smarius}
381183142Smarius
382183142Smariusstatic __inline void
383183142Smariustl_ipi_spitfire_dcache_page_inval(void)
384183142Smarius{
385183142Smarius
386183142Smarius}
387183142Smarius
388183142Smariusstatic __inline void
389183142Smariustl_ipi_spitfire_icache_page_inval(void)
390183142Smarius{
391183142Smarius
392183142Smarius}
393183142Smarius
39489051Sjake#endif /* !LOCORE */
39589051Sjake
396183142Smarius#endif /* SMP */
397183142Smarius
39880708Sjake#endif /* !_MACHINE_SMP_H_ */
399