2 * Copyright (c) 2001 Jake Burkholder.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 #ifndef _MACHINE_SMP_H_
30 #define _MACHINE_SMP_H_
34 #define CPU_TICKSYNC 1
35 #define CPU_STICKSYNC 2
37 #define CPU_BOOTSTRAP 4
41 #include <machine/intr_machdep.h>
42 #include <machine/pcb.h>
43 #include <machine/tte.h>
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
52 #define IDC_ITID_SHIFT 14
53 #define IDC_BN_SHIFT 24
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
61 #define IPI_RETRIES 5000
63 struct cpu_start_args {
71 struct tte csa_ttes[PCPU_PAGES];
74 struct ipi_cache_args {
81 struct pmap *ita_pmap;
85 #define ita_va ita_start
89 extern struct pcb stoppcbs[];
91 void cpu_mp_bootstrap(struct pcpu *pc);
92 void cpu_mp_shutdown(void);
94 typedef void cpu_ipi_selected_t(u_int, u_long, u_long, u_long);
95 extern cpu_ipi_selected_t *cpu_ipi_selected;
97 void mp_init(u_int cpu_impl);
99 extern struct mtx ipi_mtx;
100 extern struct ipi_cache_args ipi_cache_args;
101 extern struct ipi_tlb_args ipi_tlb_args;
103 extern char *mp_tramp_code;
104 extern u_long mp_tramp_code_len;
105 extern u_long mp_tramp_tlb_slots;
106 extern u_long mp_tramp_func;
108 extern void mp_startup(void);
110 extern char tl_ipi_cheetah_dcache_page_inval[];
111 extern char tl_ipi_spitfire_dcache_page_inval[];
112 extern char tl_ipi_spitfire_icache_page_inval[];
114 extern char tl_ipi_level[];
115 extern char tl_ipi_tlb_context_demap[];
116 extern char tl_ipi_tlb_page_demap[];
117 extern char tl_ipi_tlb_range_demap[];
120 ipi_all_but_self(u_int ipi)
123 cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)tl_ipi_level, ipi);
127 ipi_selected(u_int cpus, u_int ipi)
130 cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
133 #if defined(_MACHINE_PMAP_H_) && defined(_SYS_MUTEX_H_)
135 static __inline void *
136 ipi_dcache_page_inval(void *func, vm_paddr_t pa)
138 struct ipi_cache_args *ica;
142 ica = &ipi_cache_args;
143 mtx_lock_spin(&ipi_mtx);
144 ica->ica_mask = all_cpus;
146 cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
147 return (&ica->ica_mask);
150 static __inline void *
151 ipi_icache_page_inval(void *func, vm_paddr_t pa)
153 struct ipi_cache_args *ica;
157 ica = &ipi_cache_args;
158 mtx_lock_spin(&ipi_mtx);
159 ica->ica_mask = all_cpus;
161 cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
162 return (&ica->ica_mask);
165 static __inline void *
166 ipi_tlb_context_demap(struct pmap *pm)
168 struct ipi_tlb_args *ita;
173 if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
176 mtx_lock_spin(&ipi_mtx);
177 ita->ita_mask = cpus | PCPU_GET(cpumask);
179 cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
181 return (&ita->ita_mask);
184 static __inline void *
185 ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
187 struct ipi_tlb_args *ita;
192 if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
195 mtx_lock_spin(&ipi_mtx);
196 ita->ita_mask = cpus | PCPU_GET(cpumask);
199 cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
200 return (&ita->ita_mask);
203 static __inline void *
204 ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
206 struct ipi_tlb_args *ita;
211 if ((cpus = (pm->pm_active & PCPU_GET(other_cpus))) == 0)
214 mtx_lock_spin(&ipi_mtx);
215 ita->ita_mask = cpus | PCPU_GET(cpumask);
217 ita->ita_start = start;
219 cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_range_demap, (u_long)ita);
220 return (&ita->ita_mask);
224 ipi_wait(void *cookie)
226 volatile u_int *mask;
228 if ((mask = cookie) != NULL) {
229 atomic_clear_int(mask, PCPU_GET(cpumask));
232 mtx_unlock_spin(&ipi_mtx);
236 #endif /* _MACHINE_PMAP_H_ && _SYS_MUTEX_H_ */
244 static __inline void *
245 ipi_dcache_page_inval(void *func, vm_paddr_t pa)
251 static __inline void *
252 ipi_icache_page_inval(void *func, vm_paddr_t pa)
258 static __inline void *
259 ipi_tlb_context_demap(struct pmap *pm)
265 static __inline void *
266 ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
272 static __inline void *
273 ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
280 ipi_wait(void *cookie)
286 tl_ipi_cheetah_dcache_page_inval(void)
292 tl_ipi_spitfire_dcache_page_inval(void)
298 tl_ipi_spitfire_icache_page_inval(void)
307 #endif /* !_MACHINE_SMP_H_ */