smp.h revision 211050
180708Sjake/*-
280708Sjake * Copyright (c) 2001 Jake Burkholder.
380708Sjake * All rights reserved.
480708Sjake *
580708Sjake * Redistribution and use in source and binary forms, with or without
680708Sjake * modification, are permitted provided that the following conditions
780708Sjake * are met:
880708Sjake * 1. Redistributions of source code must retain the above copyright
980708Sjake *    notice, this list of conditions and the following disclaimer.
1080708Sjake * 2. Redistributions in binary form must reproduce the above copyright
1180708Sjake *    notice, this list of conditions and the following disclaimer in the
1280708Sjake *    documentation and/or other materials provided with the distribution.
1380708Sjake *
1481334Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1580708Sjake * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1680708Sjake * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1781334Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1880708Sjake * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1980708Sjake * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2080708Sjake * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2180708Sjake * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2280708Sjake * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2380708Sjake * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2480708Sjake * SUCH DAMAGE.
2580708Sjake *
2680708Sjake * $FreeBSD: head/sys/sparc64/include/smp.h 211050 2010-08-08 00:09:22Z marius $
2780708Sjake */
2880708Sjake
2980708Sjake#ifndef	_MACHINE_SMP_H_
3080708Sjake#define	_MACHINE_SMP_H_
3180708Sjake
32183142Smarius#ifdef SMP
33183142Smarius
34182730Smarius#define	CPU_TICKSYNC		1
35182730Smarius#define	CPU_STICKSYNC		2
36182730Smarius#define	CPU_INIT		3
37182730Smarius#define	CPU_BOOTSTRAP		4
3889051Sjake
3989051Sjake#ifndef	LOCORE
4089051Sjake
41209695Smarius#include <sys/proc.h>
42209695Smarius#include <sys/sched.h>
43209695Smarius
4491157Sjake#include <machine/intr_machdep.h>
45169730Skan#include <machine/pcb.h>
4691617Sjake#include <machine/tte.h>
4791157Sjake
48170846Smarius#define	IDR_BUSY			0x0000000000000001ULL
49170846Smarius#define	IDR_NACK			0x0000000000000002ULL
50170846Smarius#define	IDR_CHEETAH_ALL_BUSY		0x5555555555555555ULL
51170846Smarius#define	IDR_CHEETAH_ALL_NACK		(~IDR_CHEETAH_ALL_BUSY)
52170846Smarius#define	IDR_CHEETAH_MAX_BN_PAIRS	32
53170846Smarius#define	IDR_JALAPENO_MAX_BN_PAIRS	4
5489051Sjake
55169796Smarius#define	IDC_ITID_SHIFT			14
56170846Smarius#define	IDC_BN_SHIFT			24
57169796Smarius
5889051Sjake#define	IPI_AST		PIL_AST
5989051Sjake#define	IPI_RENDEZVOUS	PIL_RENDEZVOUS
60178048Smarius#define	IPI_PREEMPT	PIL_PREEMPT
61210601Smav#define	IPI_HARDCLOCK	PIL_HARDCLOCK
62210601Smav#define	IPI_STATCLOCK	PIL_STATCLOCK
6389051Sjake#define	IPI_STOP	PIL_STOP
64196196Sattilio#define	IPI_STOP_HARD	PIL_STOP
6589051Sjake
66135943Skensmith#define	IPI_RETRIES	5000
6789051Sjake
6889051Sjakestruct cpu_start_args {
6991783Sjake	u_int	csa_count;
7089051Sjake	u_int	csa_mid;
7189051Sjake	u_int	csa_state;
7291783Sjake	vm_offset_t csa_pcpu;
7391617Sjake	u_long	csa_tick;
74182730Smarius	u_long	csa_stick;
7591617Sjake	u_long	csa_ver;
7691617Sjake	struct	tte csa_ttes[PCPU_PAGES];
7789051Sjake};
7889051Sjake
7997001Sjakestruct ipi_cache_args {
8097001Sjake	u_int	ica_mask;
81113238Sjake	vm_paddr_t ica_pa;
8297001Sjake};
8397001Sjake
8489051Sjakestruct ipi_tlb_args {
8592199Sjake	u_int	ita_mask;
8691783Sjake	struct	pmap *ita_pmap;
8789051Sjake	u_long	ita_start;
8889051Sjake	u_long	ita_end;
8989051Sjake};
9089051Sjake#define	ita_va	ita_start
9189051Sjake
9289051Sjakestruct pcpu;
9389051Sjake
94152022Sjhbextern struct pcb stoppcbs[];
95152022Sjhb
9689051Sjakevoid	cpu_mp_bootstrap(struct pcpu *pc);
9792199Sjakevoid	cpu_mp_shutdown(void);
9889051Sjake
99170846Smariustypedef	void cpu_ipi_selected_t(u_int, u_long, u_long, u_long);
100170846Smariusextern	cpu_ipi_selected_t *cpu_ipi_selected;
101211050Smariustypedef	void cpu_ipi_single_t(u_int, u_long, u_long, u_long);
102211050Smariusextern	cpu_ipi_single_t *cpu_ipi_single;
10389051Sjake
104204152Smariusvoid	mp_init(u_int cpu_impl);
10591617Sjake
106108187Sjakeextern	struct mtx ipi_mtx;
107108187Sjakeextern	struct ipi_cache_args ipi_cache_args;
108108187Sjakeextern	struct ipi_tlb_args ipi_tlb_args;
10989051Sjake
11091617Sjakeextern	char *mp_tramp_code;
11191617Sjakeextern	u_long mp_tramp_code_len;
11291617Sjakeextern	u_long mp_tramp_tlb_slots;
11391617Sjakeextern	u_long mp_tramp_func;
11491617Sjake
11591617Sjakeextern	void mp_startup(void);
11691617Sjake
117112399Sjakeextern	char tl_ipi_cheetah_dcache_page_inval[];
118112399Sjakeextern	char tl_ipi_spitfire_dcache_page_inval[];
119112399Sjakeextern	char tl_ipi_spitfire_icache_page_inval[];
120112399Sjake
12189051Sjakeextern	char tl_ipi_level[];
12289051Sjakeextern	char tl_ipi_tlb_context_demap[];
12389051Sjakeextern	char tl_ipi_tlb_page_demap[];
12489051Sjakeextern	char tl_ipi_tlb_range_demap[];
12589051Sjake
126183142Smariusstatic __inline void
127183142Smariusipi_all_but_self(u_int ipi)
128183142Smarius{
12989051Sjake
130183142Smarius	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)tl_ipi_level, ipi);
131183142Smarius}
132183142Smarius
133183142Smariusstatic __inline void
134183142Smariusipi_selected(u_int cpus, u_int ipi)
135183142Smarius{
136183142Smarius
137183142Smarius	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
138183142Smarius}
139183142Smarius
140210939Sjhbstatic __inline void
141210939Sjhbipi_cpu(int cpu, u_int ipi)
142210939Sjhb{
143210939Sjhb
144211050Smarius	cpu_ipi_single(cpu, 0, (u_long)tl_ipi_level, ipi);
145210939Sjhb}
146210939Sjhb
147108187Sjake#if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_)
148108187Sjake
14997001Sjakestatic __inline void *
150113238Sjakeipi_dcache_page_inval(void *func, vm_paddr_t pa)
15197001Sjake{
15297001Sjake	struct ipi_cache_args *ica;
15397001Sjake
15497001Sjake	if (smp_cpus == 1)
15597001Sjake		return (NULL);
156209695Smarius	sched_pin();
15797001Sjake	ica = &ipi_cache_args;
158108187Sjake	mtx_lock_spin(&ipi_mtx);
15997001Sjake	ica->ica_mask = all_cpus;
16097001Sjake	ica->ica_pa = pa;
161112399Sjake	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
16297001Sjake	return (&ica->ica_mask);
16397001Sjake}
16497001Sjake
16597001Sjakestatic __inline void *
166113238Sjakeipi_icache_page_inval(void *func, vm_paddr_t pa)
16797001Sjake{
16897001Sjake	struct ipi_cache_args *ica;
16997001Sjake
17097001Sjake	if (smp_cpus == 1)
17197001Sjake		return (NULL);
172209695Smarius	sched_pin();
17397001Sjake	ica = &ipi_cache_args;
174108187Sjake	mtx_lock_spin(&ipi_mtx);
17597001Sjake	ica->ica_mask = all_cpus;
17697001Sjake	ica->ica_pa = pa;
177112399Sjake	cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
17897001Sjake	return (&ica->ica_mask);
17997001Sjake}
18097001Sjake
18189051Sjakestatic __inline void *
18291783Sjakeipi_tlb_context_demap(struct pmap *pm)
18389051Sjake{
18489051Sjake	struct ipi_tlb_args *ita;
18591783Sjake	u_int cpus;
18689051Sjake
18791783Sjake	if (smp_cpus == 1)
18889051Sjake		return (NULL);
189209695Smarius	sched_pin();
190209695Smarius	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0) {
191209695Smarius		sched_unpin();
19291783Sjake		return (NULL);
193209695Smarius	}
19489051Sjake	ita = &ipi_tlb_args;
195108187Sjake	mtx_lock_spin(&ipi_mtx);
19692199Sjake	ita->ita_mask = cpus | PCPU_GET(cpumask);
19791783Sjake	ita->ita_pmap = pm;
19891783Sjake	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
19991783Sjake	    (u_long)ita);
20092199Sjake	return (&ita->ita_mask);
20189051Sjake}
20289051Sjake
20389051Sjakestatic __inline void *
204100718Sjakeipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
20589051Sjake{
20689051Sjake	struct ipi_tlb_args *ita;
20791783Sjake	u_int cpus;
20889051Sjake
20991783Sjake	if (smp_cpus == 1)
21089051Sjake		return (NULL);
211209695Smarius	sched_pin();
212209695Smarius	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0) {
213209695Smarius		sched_unpin();
21491783Sjake		return (NULL);
215209695Smarius	}
21689051Sjake	ita = &ipi_tlb_args;
217108187Sjake	mtx_lock_spin(&ipi_mtx);
21892199Sjake	ita->ita_mask = cpus | PCPU_GET(cpumask);
21991783Sjake	ita->ita_pmap = pm;
22089051Sjake	ita->ita_va = va;
22191783Sjake	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
22292199Sjake	return (&ita->ita_mask);
22389051Sjake}
22489051Sjake
22589051Sjakestatic __inline void *
22691783Sjakeipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
22789051Sjake{
22889051Sjake	struct ipi_tlb_args *ita;
22991783Sjake	u_int cpus;
23089051Sjake
23191783Sjake	if (smp_cpus == 1)
23289051Sjake		return (NULL);
233209695Smarius	sched_pin();
234209695Smarius	if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0) {
235209695Smarius		sched_unpin();
23691783Sjake		return (NULL);
237209695Smarius	}
23889051Sjake	ita = &ipi_tlb_args;
239108187Sjake	mtx_lock_spin(&ipi_mtx);
24092199Sjake	ita->ita_mask = cpus | PCPU_GET(cpumask);
24191783Sjake	ita->ita_pmap = pm;
24289051Sjake	ita->ita_start = start;
24389051Sjake	ita->ita_end = end;
244211050Smarius	cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap,
245211050Smarius	    (u_long)ita);
24692199Sjake	return (&ita->ita_mask);
24789051Sjake}
24889051Sjake
24989051Sjakestatic __inline void
25089051Sjakeipi_wait(void *cookie)
25189051Sjake{
252143190Salc	volatile u_int *mask;
25389051Sjake
25492199Sjake	if ((mask = cookie) != NULL) {
25592199Sjake		atomic_clear_int(mask, PCPU_GET(cpumask));
25692199Sjake		while (*mask != 0)
25791617Sjake			;
258108187Sjake		mtx_unlock_spin(&ipi_mtx);
259209695Smarius		sched_unpin();
26089051Sjake	}
26189051Sjake}
26289051Sjake
263108187Sjake#endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
26491783Sjake
265183142Smarius#endif /* !LOCORE */
266183142Smarius
26789051Sjake#else
26889051Sjake
269183142Smarius#ifndef	LOCORE
270183142Smarius
27189051Sjakestatic __inline void *
272209695Smariusipi_dcache_page_inval(void *func __unused, vm_paddr_t pa __unused)
27397001Sjake{
274169796Smarius
27597001Sjake	return (NULL);
27697001Sjake}
27797001Sjake
27897001Sjakestatic __inline void *
279209695Smariusipi_icache_page_inval(void *func __unused, vm_paddr_t pa __unused)
28097001Sjake{
281169796Smarius
28297001Sjake	return (NULL);
28397001Sjake}
28497001Sjake
28597001Sjakestatic __inline void *
286209695Smariusipi_tlb_context_demap(struct pmap *pm __unused)
28789051Sjake{
288169796Smarius
28989051Sjake	return (NULL);
29089051Sjake}
29189051Sjake
29289051Sjakestatic __inline void *
293209695Smariusipi_tlb_page_demap(struct pmap *pm __unused, vm_offset_t va __unused)
29489051Sjake{
295169796Smarius
29689051Sjake	return (NULL);
29789051Sjake}
29889051Sjake
29989051Sjakestatic __inline void *
300209695Smariusipi_tlb_range_demap(struct pmap *pm __unused, vm_offset_t start __unused,
301209695Smarius    __unused vm_offset_t end)
30289051Sjake{
303169796Smarius
30489051Sjake	return (NULL);
30589051Sjake}
30689051Sjake
30789051Sjakestatic __inline void
30889051Sjakeipi_wait(void *cookie)
30989051Sjake{
310169796Smarius
31189051Sjake}
31289051Sjake
313183142Smariusstatic __inline void
314183142Smariustl_ipi_cheetah_dcache_page_inval(void)
315183142Smarius{
31689051Sjake
317183142Smarius}
318183142Smarius
319183142Smariusstatic __inline void
320183142Smariustl_ipi_spitfire_dcache_page_inval(void)
321183142Smarius{
322183142Smarius
323183142Smarius}
324183142Smarius
325183142Smariusstatic __inline void
326183142Smariustl_ipi_spitfire_icache_page_inval(void)
327183142Smarius{
328183142Smarius
329183142Smarius}
330183142Smarius
33189051Sjake#endif /* !LOCORE */
33289051Sjake
333183142Smarius#endif /* SMP */
334183142Smarius
33580708Sjake#endif /* !_MACHINE_SMP_H_ */
336