Deleted Added
full compact
mp_machdep.c (91066) mp_machdep.c (91617)
1/*-
2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 38 unchanged lines hidden (view full) ---

47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
1/*-
2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

--- 38 unchanged lines hidden (view full) ---

47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 * $FreeBSD: head/sys/sparc64/sparc64/mp_machdep.c 91066 2002-02-22 13:32:01Z phk $
55 * $FreeBSD: head/sys/sparc64/sparc64/mp_machdep.c 91617 2002-03-04 07:12:36Z jake $
56 */
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/lock.h>
61#include <sys/kernel.h>
62#include <sys/ktr.h>
63#include <sys/mutex.h>

--- 8 unchanged lines hidden (view full) ---

72#include <vm/vm_extern.h>
73#include <vm/vm_map.h>
74
75#include <dev/ofw/openfirm.h>
76
77#include <machine/asi.h>
78#include <machine/md_var.h>
79#include <machine/smp.h>
56 */
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/lock.h>
61#include <sys/kernel.h>
62#include <sys/ktr.h>
63#include <sys/mutex.h>

--- 8 unchanged lines hidden (view full) ---

72#include <vm/vm_extern.h>
73#include <vm/vm_map.h>
74
75#include <dev/ofw/openfirm.h>
76
77#include <machine/asi.h>
78#include <machine/md_var.h>
79#include <machine/smp.h>
80#include <machine/tlb.h>
80#include <machine/tte.h>
81
82static ih_func_t cpu_ipi_ast;
83static ih_func_t cpu_ipi_stop;
84
85/*
86 * Argument area used to pass data to non-boot processors as they start up.
87 * This must be statically initialized with a known invalid upa module id,
88 * since the other processors will use it before the boot cpu enters the
89 * kernel.
90 */
91struct cpu_start_args cpu_start_args = { -1, -1, 0, 0 };
92
81#include <machine/tte.h>
82
83static ih_func_t cpu_ipi_ast;
84static ih_func_t cpu_ipi_stop;
85
86/*
87 * Argument area used to pass data to non-boot processors as they start up.
88 * This must be statically initialized with a known invalid upa module id,
89 * since the other processors will use it before the boot cpu enters the
90 * kernel.
91 */
92struct cpu_start_args cpu_start_args = { -1, -1, 0, 0 };
93
94vm_offset_t mp_tramp;
95
93static struct mtx ap_boot_mtx;
94
95u_int mp_boot_mid;
96
96static struct mtx ap_boot_mtx;
97
98u_int mp_boot_mid;
99
100void cpu_mp_unleash(void *);
101SYSINIT(cpu_mp_unleash, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
102
103vm_offset_t
104mp_tramp_alloc(void)
105{
106 struct tte *tp;
107 char *v;
108 int i;
109
110 v = OF_claim(NULL, PAGE_SIZE, PAGE_SIZE);
111 if (v == NULL)
112 panic("mp_tramp_alloc");
113 bcopy(mp_tramp_code, v, mp_tramp_code_len);
114 *(u_long *)(v + mp_tramp_tlb_slots) = kernel_tlb_slots;
115 *(u_long *)(v + mp_tramp_func) = (u_long)mp_startup;
116 tp = (struct tte *)(v + mp_tramp_code_len);
117 for (i = 0; i < kernel_tlb_slots; i++)
118 tp[i] = kernel_ttes[i];
119 for (i = 0; i < PAGE_SIZE; i += sizeof(long))
120 flush(v + i);
121 return (vm_offset_t)v;
122}
123
97/*
98 * Probe for other cpus.
99 */
100int
101cpu_mp_probe(void)
102{
103 phandle_t child;
104 phandle_t root;

--- 9 unchanged lines hidden (view full) ---

114 for (child = OF_child(root); child != 0; child = OF_peer(child)) {
115 if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 &&
116 strcmp(buf, "cpu") == 0)
117 cpus++;
118 }
119 return (cpus > 1);
120}
121
124/*
125 * Probe for other cpus.
126 */
127int
128cpu_mp_probe(void)
129{
130 phandle_t child;
131 phandle_t root;

--- 9 unchanged lines hidden (view full) ---

141 for (child = OF_child(root); child != 0; child = OF_peer(child)) {
142 if (OF_getprop(child, "device_type", buf, sizeof(buf)) > 0 &&
143 strcmp(buf, "cpu") == 0)
144 cpus++;
145 }
146 return (cpus > 1);
147}
148
149static void
150sun4u_startcpu(phandle_t cpu, void *func, u_long arg)
151{
152 static struct {
153 cell_t name;
154 cell_t nargs;
155 cell_t nreturns;
156 cell_t cpu;
157 cell_t func;
158 cell_t arg;
159 } args = {
160 (cell_t)"SUNW,start-cpu",
161 3,
162 0,
163 0,
164 0,
165 0
166 };
167
168 args.cpu = cpu;
169 args.func = (cell_t)func;
170 args.arg = (cell_t)arg;
171 openfirmware(&args);
172}
173
122/*
123 * Fire up any non-boot processors.
124 */
125void
126cpu_mp_start(void)
127{
128 volatile struct cpu_start_args *csa;
129 struct pcpu *pc;
130 phandle_t child;
131 phandle_t root;
174/*
175 * Fire up any non-boot processors.
176 */
177void
178cpu_mp_start(void)
179{
180 volatile struct cpu_start_args *csa;
181 struct pcpu *pc;
182 phandle_t child;
183 phandle_t root;
132 vm_offset_t pa;
133 vm_offset_t va;
134 char buf[128];
184 vm_offset_t va;
185 char buf[128];
135 u_long data;
136 u_int mid;
186 u_int clock;
137 int cpuid;
187 int cpuid;
188 u_int mid;
189 u_long s;
138
139 mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN);
140
141 intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL);
142 intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action,
143 -1, NULL, NULL);
144 intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL);
145
146 root = OF_peer(0);
147 csa = &cpu_start_args;
148 for (child = OF_child(root); child != 0; child = OF_peer(child)) {
149 if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0 ||
150 strcmp(buf, "cpu") != 0)
151 continue;
152 if (OF_getprop(child, "upa-portid", &mid, sizeof(mid)) <= 0)
153 panic("cpu_mp_start: can't get module id");
154 if (mid == mp_boot_mid)
155 continue;
190
191 mtx_init(&ap_boot_mtx, "ap boot", MTX_SPIN);
192
193 intr_setup(PIL_AST, cpu_ipi_ast, -1, NULL, NULL);
194 intr_setup(PIL_RENDEZVOUS, (ih_func_t *)smp_rendezvous_action,
195 -1, NULL, NULL);
196 intr_setup(PIL_STOP, cpu_ipi_stop, -1, NULL, NULL);
197
198 root = OF_peer(0);
199 csa = &cpu_start_args;
200 for (child = OF_child(root); child != 0; child = OF_peer(child)) {
201 if (OF_getprop(child, "device_type", buf, sizeof(buf)) <= 0 ||
202 strcmp(buf, "cpu") != 0)
203 continue;
204 if (OF_getprop(child, "upa-portid", &mid, sizeof(mid)) <= 0)
205 panic("cpu_mp_start: can't get module id");
206 if (mid == mp_boot_mid)
207 continue;
208 if (OF_getprop(child, "clock-frequency", &clock,
209 sizeof(clock)) <= 0)
210 panic("cpu_mp_start: can't get clock");
156
211
157 /*
158 * Found a non-boot processor. It is currently spinning in
159 * _mp_start, and it has no stack. Allocate a per-cpu page
160 * for it, which it will use as a bootstrap stack, and pass
161 * it through the argument area.
162 */
212 csa->csa_state = 0;
213 sun4u_startcpu(child, (void *)mp_tramp, 0);
214 s = intr_disable();
215 while (csa->csa_state != CPU_CLKSYNC)
216 ;
217 membar(StoreLoad);
218 csa->csa_tick = rd(tick);
219 while (csa->csa_state != CPU_INIT)
220 ;
221 csa->csa_tick = 0;
222 intr_restore(s);
223
163 cpuid = mp_ncpus++;
224 cpuid = mp_ncpus++;
164 va = kmem_alloc(kernel_map, PAGE_SIZE);
165 pa = pmap_kextract(va);
166 if (pa == 0)
167 panic("cpu_mp_start: pmap_kextract\n");
168 pc = (struct pcpu *)(va + PAGE_SIZE) - 1;
225 cpu_identify(csa->csa_ver, clock, cpuid);
226
227 va = kmem_alloc(kernel_map, PCPU_PAGES * PAGE_SIZE);
228 pc = (struct pcpu *)(va + (PCPU_PAGES * PAGE_SIZE)) - 1;
169 pcpu_init(pc, cpuid, sizeof(*pc));
229 pcpu_init(pc, cpuid, sizeof(*pc));
230 pc->pc_addr = va;
170 pc->pc_mid = mid;
231 pc->pc_mid = mid;
171 data = TD_V | TD_8K | TD_VA_LOW(va) | TD_PA(pa) |
172 TD_L | TD_CP | TD_CV | TD_P | TD_W;
173
232
174 /*
175 * Initialize the argument area to start this cpu.
176 * Note, order is important here. We must set the pcpu pointer
177 * and the tte data before letting it loose.
178 */
179 csa->csa_data = data;
180 csa->csa_va = va;
181 membar(StoreLoad);
182 csa->csa_mid = mid;
183 csa->csa_state = CPU_STARTING;
184 while (csa->csa_state == CPU_STARTING)
185 membar(StoreLoad);
186 if (csa->csa_state != CPU_STARTED)
187 panic("cpu_mp_start: bad state %d for cpu %d\n",
188 csa->csa_state, mid);
189 csa->csa_state = CPU_BOOTSTRAPING;
190 while (csa->csa_state == CPU_BOOTSTRAPING)
191 membar(StoreLoad);
192 if (csa->csa_state != CPU_BOOTSTRAPPED)
193 panic("cpu_mp_start: bad state %d for cpu %d\n",
194 csa->csa_state, mid);
195 cpu_ipi_send(mid, 0, (u_long)tl_ipi_test, 0);
196 all_cpus |= 1 << cpuid;
197 }
198 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
199}
200
201void
202cpu_mp_announce(void)
203{
233 all_cpus |= 1 << cpuid;
234 }
235 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
236}
237
238void
239cpu_mp_announce(void)
240{
204 TODO;
205}
206
207void
241}
242
243void
208cpu_mp_bootstrap(struct pcpu *pc)
244cpu_mp_unleash(void *v)
209{
245{
210 struct cpu_start_args *csa;
246 volatile struct cpu_start_args *csa;
247 struct pcpu *pc;
248 vm_offset_t pa;
249 vm_offset_t va;
250 u_int ctx_min;
251 u_int ctx_inc;
252 u_long s;
253 int i;
211
254
255 ctx_min = 1;
256 ctx_inc = (8192 - 1) / mp_ncpus;
212 csa = &cpu_start_args;
257 csa = &cpu_start_args;
213 CTR1(KTR_SMP, "cpu_mp_bootstrap: cpuid=%d", pc->pc_cpuid);
214 while (csa->csa_state != CPU_BOOTSTRAPING)
215 membar(StoreLoad);
216 cpu_setregs(pc);
217 pmap_map_tsb();
258 SLIST_FOREACH(pc, &cpuhead, pc_allcpu) {
259 pc->pc_tlb_ctx = ctx_min;
260 pc->pc_tlb_ctx_min = ctx_min;
261 pc->pc_tlb_ctx_max = ctx_min + ctx_inc;
262 ctx_min += ctx_inc;
218
263
219 CTR0(KTR_SMP, "cpu_mp_bootstrap: spinning");
220 csa->csa_state = CPU_BOOTSTRAPPED;
221 membar(StoreLoad);
222 for (;;)
223 ;
264 if (pc->pc_cpuid == PCPU_GET(cpuid))
265 continue;
266 KASSERT(pc->pc_idlethread != NULL,
267 ("cpu_mp_unleash: idlethread"));
268 KASSERT(pc->pc_curthread == pc->pc_idlethread,
269 ("cpu_mp_unleash: curthread"));
270
271 pc->pc_curpcb = pc->pc_curthread->td_pcb;
272 for (i = 0; i < PCPU_PAGES; i++) {
273 va = pc->pc_addr + i * PAGE_SIZE;
274 pa = pmap_kextract(va);
275 if (pa == 0)
276 panic("cpu_mp_unleash: pmap_kextract\n");
277 csa->csa_ttes[i].tte_vpn = TV_VPN(va);
278 csa->csa_ttes[i].tte_data = TD_V | TD_8K | TD_PA(pa) |
279 TD_L | TD_CP | TD_CV | TD_P | TD_W;
280 }
281 csa->csa_state = 0;
282 csa->csa_mid = pc->pc_mid;
283 s = intr_disable();
284 while (csa->csa_state != CPU_BOOTSTRAP)
285 ;
286 intr_restore(s);
287 }
288}
224
289
225 mtx_lock_spin(&ap_boot_mtx);
290void
291cpu_mp_bootstrap(struct pcpu *pc)
292{
293 volatile struct cpu_start_args *csa;
226
294
227 CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid));
295 csa = &cpu_start_args;
296 pmap_map_tsb();
297 cpu_setregs(pc);
228
229 smp_cpus++;
298
299 smp_cpus++;
230
231 /* Build our map of 'other' CPUs. */
232 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
300 PCPU_SET(other_cpus, all_cpus & ~(1 << PCPU_GET(cpuid)));
233
234 printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
235
301 printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
302
236 if (smp_cpus == mp_ncpus) {
237 smp_started = 1; /* enable IPI's, tlb shootdown, freezes etc */
238 smp_active = 1; /* historic */
239 }
303 csa->csa_state = CPU_BOOTSTRAP;
304 for (;;)
305 ;
240
306
241 mtx_unlock_spin(&ap_boot_mtx);
242
243 /* wait until all the AP's are up */
244 while (smp_started == 0)
245 ; /* nothing */
246
247 binuptime(PCPU_PTR(switchtime));
248 PCPU_SET(switchticks, ticks);
249
250 /* ok, now grab sched_lock and enter the scheduler */
251 mtx_lock_spin(&sched_lock);
252 cpu_throw(); /* doesn't return */
253}
254

--- 68 unchanged lines hidden ---
307 binuptime(PCPU_PTR(switchtime));
308 PCPU_SET(switchticks, ticks);
309
310 /* ok, now grab sched_lock and enter the scheduler */
311 mtx_lock_spin(&sched_lock);
312 cpu_throw(); /* doesn't return */
313}
314

--- 68 unchanged lines hidden ---