]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/i386/i386/mp_machdep.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / i386 / i386 / mp_machdep.c
1 /*-
2  * Copyright (c) 1996, by Steve Passe
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. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #include "opt_apic.h"
30 #include "opt_cpu.h"
31 #include "opt_kstack_pages.h"
32 #include "opt_mp_watchdog.h"
33 #include "opt_sched.h"
34 #include "opt_smp.h"
35
36 #if !defined(lint)
37 #if !defined(SMP)
38 #error How did you get here?
39 #endif
40
41 #ifndef DEV_APIC
42 #error The apic device is required for SMP, add "device apic" to your config file.
43 #endif
44 #if defined(CPU_DISABLE_CMPXCHG) && !defined(COMPILING_LINT)
45 #error SMP not supported with CPU_DISABLE_CMPXCHG
46 #endif
47 #endif /* not lint */
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/bus.h>
52 #include <sys/cons.h>   /* cngetc() */
53 #ifdef GPROF 
54 #include <sys/gmon.h>
55 #endif
56 #include <sys/kernel.h>
57 #include <sys/ktr.h>
58 #include <sys/lock.h>
59 #include <sys/malloc.h>
60 #include <sys/memrange.h>
61 #include <sys/mutex.h>
62 #include <sys/pcpu.h>
63 #include <sys/proc.h>
64 #include <sys/sched.h>
65 #include <sys/smp.h>
66 #include <sys/sysctl.h>
67
68 #include <vm/vm.h>
69 #include <vm/vm_param.h>
70 #include <vm/pmap.h>
71 #include <vm/vm_kern.h>
72 #include <vm/vm_extern.h>
73
74 #include <machine/apicreg.h>
75 #include <machine/md_var.h>
76 #include <machine/mp_watchdog.h>
77 #include <machine/pcb.h>
78 #include <machine/psl.h>
79 #include <machine/smp.h>
80 #include <machine/specialreg.h>
81
82 #define WARMBOOT_TARGET         0
83 #define WARMBOOT_OFF            (KERNBASE + 0x0467)
84 #define WARMBOOT_SEG            (KERNBASE + 0x0469)
85
86 #define CMOS_REG                (0x70)
87 #define CMOS_DATA               (0x71)
88 #define BIOS_RESET              (0x0f)
89 #define BIOS_WARM               (0x0a)
90
91 /*
92  * this code MUST be enabled here and in mpboot.s.
93  * it follows the very early stages of AP boot by placing values in CMOS ram.
94  * it NORMALLY will never be needed and thus the primitive method for enabling.
95  *
96 #define CHECK_POINTS
97  */
98
99 #if defined(CHECK_POINTS) && !defined(PC98)
100 #define CHECK_READ(A)    (outb(CMOS_REG, (A)), inb(CMOS_DATA))
101 #define CHECK_WRITE(A,D) (outb(CMOS_REG, (A)), outb(CMOS_DATA, (D)))
102
103 #define CHECK_INIT(D);                          \
104         CHECK_WRITE(0x34, (D));                 \
105         CHECK_WRITE(0x35, (D));                 \
106         CHECK_WRITE(0x36, (D));                 \
107         CHECK_WRITE(0x37, (D));                 \
108         CHECK_WRITE(0x38, (D));                 \
109         CHECK_WRITE(0x39, (D));
110
111 #define CHECK_PRINT(S);                         \
112         printf("%s: %d, %d, %d, %d, %d, %d\n",  \
113            (S),                                 \
114            CHECK_READ(0x34),                    \
115            CHECK_READ(0x35),                    \
116            CHECK_READ(0x36),                    \
117            CHECK_READ(0x37),                    \
118            CHECK_READ(0x38),                    \
119            CHECK_READ(0x39));
120
121 #else                           /* CHECK_POINTS */
122
123 #define CHECK_INIT(D)
124 #define CHECK_PRINT(S)
125 #define CHECK_WRITE(A, D)
126
127 #endif                          /* CHECK_POINTS */
128
129 /* lock region used by kernel profiling */
130 int     mcount_lock;
131
132 int     mp_naps;                /* # of Applications processors */
133 int     boot_cpu_id = -1;       /* designated BSP */
134
135 extern  struct pcpu __pcpu[];
136
137 /* AP uses this during bootstrap.  Do not staticize.  */
138 char *bootSTK;
139 static int bootAP;
140
141 /* Free these after use */
142 void *bootstacks[MAXCPU];
143
144 /* Hotwire a 0->4MB V==P mapping */
145 extern pt_entry_t *KPTphys;
146
147 struct pcb stoppcbs[MAXCPU];
148
149 /* Variables needed for SMP tlb shootdown. */
150 vm_offset_t smp_tlb_addr1;
151 vm_offset_t smp_tlb_addr2;
152 volatile int smp_tlb_wait;
153
154 #ifdef STOP_NMI
155 volatile cpumask_t ipi_nmi_pending;
156
157 static void     ipi_nmi_selected(u_int32_t cpus);
158 #endif 
159
160 #ifdef COUNT_IPIS
161 /* Interrupt counts. */
162 static u_long *ipi_preempt_counts[MAXCPU];
163 static u_long *ipi_ast_counts[MAXCPU];
164 u_long *ipi_invltlb_counts[MAXCPU];
165 u_long *ipi_invlrng_counts[MAXCPU];
166 u_long *ipi_invlpg_counts[MAXCPU];
167 u_long *ipi_invlcache_counts[MAXCPU];
168 u_long *ipi_rendezvous_counts[MAXCPU];
169 u_long *ipi_lazypmap_counts[MAXCPU];
170 #endif
171
172 /*
173  * Local data and functions.
174  */
175
176 #ifdef STOP_NMI
177 /* 
178  * Provide an alternate method of stopping other CPUs. If another CPU has
179  * disabled interrupts the conventional STOP IPI will be blocked. This 
180  * NMI-based stop should get through in that case.
181  */
182 static int stop_cpus_with_nmi = 1;
183 SYSCTL_INT(_debug, OID_AUTO, stop_cpus_with_nmi, CTLTYPE_INT | CTLFLAG_RW,
184     &stop_cpus_with_nmi, 0, "");
185 TUNABLE_INT("debug.stop_cpus_with_nmi", &stop_cpus_with_nmi);
186 #else
187 #define stop_cpus_with_nmi      0
188 #endif
189
190 static u_int logical_cpus;
191
192 /* used to hold the AP's until we are ready to release them */
193 static struct mtx ap_boot_mtx;
194
195 /* Set to 1 once we're ready to let the APs out of the pen. */
196 static volatile int aps_ready = 0;
197
198 /*
199  * Store data from cpu_add() until later in the boot when we actually setup
200  * the APs.
201  */
202 struct cpu_info {
203         int     cpu_present:1;
204         int     cpu_bsp:1;
205         int     cpu_disabled:1;
206 } static cpu_info[MAX_APIC_ID + 1];
207 int cpu_apic_ids[MAXCPU];
208
209 /* Holds pending bitmap based IPIs per CPU */
210 static volatile u_int cpu_ipi_pending[MAXCPU];
211
212 static u_int boot_address;
213
214 static void     assign_cpu_ids(void);
215 static void     install_ap_tramp(void);
216 static void     set_interrupt_apic_ids(void);
217 static int      start_all_aps(void);
218 static int      start_ap(int apic_id);
219 static void     release_aps(void *dummy);
220
221 static int      hlt_logical_cpus;
222 static u_int    hyperthreading_cpus;
223 static cpumask_t        hyperthreading_cpus_mask;
224 static int      hyperthreading_allowed = 1;
225 static struct   sysctl_ctx_list logical_cpu_clist;
226
227 static void
228 mem_range_AP_init(void)
229 {
230         if (mem_range_softc.mr_op && mem_range_softc.mr_op->initAP)
231                 mem_range_softc.mr_op->initAP(&mem_range_softc);
232 }
233
234 struct cpu_group *
235 cpu_topo(void)
236 {
237         if (cpu_cores == 0)
238                 cpu_cores = 1;
239         if (cpu_logical == 0)
240                 cpu_logical = 1;
241         if (mp_ncpus % (cpu_cores * cpu_logical) != 0) {
242                 printf("WARNING: Non-uniform processors.\n");
243                 printf("WARNING: Using suboptimal topology.\n");
244                 return (smp_topo_none());
245         }
246         /*
247          * No multi-core or hyper-threaded.
248          */
249         if (cpu_logical * cpu_cores == 1)
250                 return (smp_topo_none());
251         /*
252          * Only HTT no multi-core.
253          */
254         if (cpu_logical > 1 && cpu_cores == 1)
255                 return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
256         /*
257          * Only multi-core no HTT.
258          */
259         if (cpu_cores > 1 && cpu_logical == 1)
260                 return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0));
261         /*
262          * Both HTT and multi-core.
263          */
264         return (smp_topo_2level(CG_SHARE_NONE, cpu_cores,
265             CG_SHARE_L1, cpu_logical, CG_FLAG_HTT));
266 }
267
268
269 /*
270  * Calculate usable address in base memory for AP trampoline code.
271  */
272 u_int
273 mp_bootaddress(u_int basemem)
274 {
275
276         boot_address = trunc_page(basemem);     /* round down to 4k boundary */
277         if ((basemem - boot_address) < bootMP_size)
278                 boot_address -= PAGE_SIZE;      /* not enough, lower by 4k */
279
280         return boot_address;
281 }
282
283 void
284 cpu_add(u_int apic_id, char boot_cpu)
285 {
286
287         if (apic_id > MAX_APIC_ID) {
288                 panic("SMP: APIC ID %d too high", apic_id);
289                 return;
290         }
291         KASSERT(cpu_info[apic_id].cpu_present == 0, ("CPU %d added twice",
292             apic_id));
293         cpu_info[apic_id].cpu_present = 1;
294         if (boot_cpu) {
295                 KASSERT(boot_cpu_id == -1,
296                     ("CPU %d claims to be BSP, but CPU %d already is", apic_id,
297                     boot_cpu_id));
298                 boot_cpu_id = apic_id;
299                 cpu_info[apic_id].cpu_bsp = 1;
300         }
301         if (mp_ncpus < MAXCPU)
302                 mp_ncpus++;
303         if (bootverbose)
304                 printf("SMP: Added CPU %d (%s)\n", apic_id, boot_cpu ? "BSP" :
305                     "AP");
306 }
307
308 void
309 cpu_mp_setmaxid(void)
310 {
311
312         mp_maxid = MAXCPU - 1;
313 }
314
315 int
316 cpu_mp_probe(void)
317 {
318
319         /*
320          * Always record BSP in CPU map so that the mbuf init code works
321          * correctly.
322          */
323         all_cpus = 1;
324         if (mp_ncpus == 0) {
325                 /*
326                  * No CPUs were found, so this must be a UP system.  Setup
327                  * the variables to represent a system with a single CPU
328                  * with an id of 0.
329                  */
330                 mp_ncpus = 1;
331                 return (0);
332         }
333
334         /* At least one CPU was found. */
335         if (mp_ncpus == 1) {
336                 /*
337                  * One CPU was found, so this must be a UP system with
338                  * an I/O APIC.
339                  */
340                 return (0);
341         }
342
343         /* At least two CPUs were found. */
344         return (1);
345 }
346
347 /*
348  * Initialize the IPI handlers and start up the AP's.
349  */
350 void
351 cpu_mp_start(void)
352 {
353         int i;
354         u_int threads_per_cache, p[4];
355
356         /* Initialize the logical ID to APIC ID table. */
357         for (i = 0; i < MAXCPU; i++) {
358                 cpu_apic_ids[i] = -1;
359                 cpu_ipi_pending[i] = 0;
360         }
361
362         /* Install an inter-CPU IPI for TLB invalidation */
363         setidt(IPI_INVLTLB, IDTVEC(invltlb),
364                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
365         setidt(IPI_INVLPG, IDTVEC(invlpg),
366                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
367         setidt(IPI_INVLRNG, IDTVEC(invlrng),
368                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
369
370         /* Install an inter-CPU IPI for cache invalidation. */
371         setidt(IPI_INVLCACHE, IDTVEC(invlcache),
372                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
373
374         /* Install an inter-CPU IPI for lazy pmap release */
375         setidt(IPI_LAZYPMAP, IDTVEC(lazypmap),
376                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
377
378         /* Install an inter-CPU IPI for all-CPU rendezvous */
379         setidt(IPI_RENDEZVOUS, IDTVEC(rendezvous),
380                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
381
382         /* Install generic inter-CPU IPI handler */
383         setidt(IPI_BITMAP_VECTOR, IDTVEC(ipi_intr_bitmap_handler),
384                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
385
386         /* Install an inter-CPU IPI for CPU stop/restart */
387         setidt(IPI_STOP, IDTVEC(cpustop),
388                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
389
390
391         /* Set boot_cpu_id if needed. */
392         if (boot_cpu_id == -1) {
393                 boot_cpu_id = PCPU_GET(apic_id);
394                 cpu_info[boot_cpu_id].cpu_bsp = 1;
395         } else
396                 KASSERT(boot_cpu_id == PCPU_GET(apic_id),
397                     ("BSP's APIC ID doesn't match boot_cpu_id"));
398         cpu_apic_ids[0] = boot_cpu_id;
399
400         assign_cpu_ids();
401
402         /* Start each Application Processor */
403         start_all_aps();
404
405         /* Setup the initial logical CPUs info. */
406         logical_cpus = logical_cpus_mask = 0;
407         if (cpu_feature & CPUID_HTT)
408                 logical_cpus = (cpu_procinfo & CPUID_HTT_CORES) >> 16;
409
410         /*
411          * Work out if hyperthreading is *really* enabled.  This
412          * is made really ugly by the fact that processors lie: Dual
413          * core processors claim to be hyperthreaded even when they're
414          * not, presumably because they want to be treated the same
415          * way as HTT with respect to per-cpu software licensing.
416          * At the time of writing (May 12, 2005) the only hyperthreaded
417          * cpus are from Intel, and Intel's dual-core processors can be
418          * identified via the "deterministic cache parameters" cpuid
419          * calls.
420          */
421         /*
422          * First determine if this is an Intel processor which claims
423          * to have hyperthreading support.
424          */
425         if ((cpu_feature & CPUID_HTT) &&
426             (strcmp(cpu_vendor, "GenuineIntel") == 0)) {
427                 /*
428                  * If the "deterministic cache parameters" cpuid calls
429                  * are available, use them.
430                  */
431                 if (cpu_high >= 4) {
432                         /* Ask the processor about the L1 cache. */
433                         for (i = 0; i < 1; i++) {
434                                 cpuid_count(4, i, p);
435                                 threads_per_cache = ((p[0] & 0x3ffc000) >> 14) + 1;
436                                 if (hyperthreading_cpus < threads_per_cache)
437                                         hyperthreading_cpus = threads_per_cache;
438                                 if ((p[0] & 0x1f) == 0)
439                                         break;
440                         }
441                 }
442
443                 /*
444                  * If the deterministic cache parameters are not
445                  * available, or if no caches were reported to exist,
446                  * just accept what the HTT flag indicated.
447                  */
448                 if (hyperthreading_cpus == 0)
449                         hyperthreading_cpus = logical_cpus;
450         }
451
452         set_interrupt_apic_ids();
453 }
454
455
456 /*
457  * Print various information about the SMP system hardware and setup.
458  */
459 void
460 cpu_mp_announce(void)
461 {
462         int i, x;
463
464         /* List CPUs */
465         printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
466         for (i = 1, x = 0; x <= MAX_APIC_ID; x++) {
467                 if (!cpu_info[x].cpu_present || cpu_info[x].cpu_bsp)
468                         continue;
469                 if (cpu_info[x].cpu_disabled)
470                         printf("  cpu (AP): APIC ID: %2d (disabled)\n", x);
471                 else {
472                         KASSERT(i < mp_ncpus,
473                             ("mp_ncpus and actual cpus are out of whack"));
474                         printf(" cpu%d (AP): APIC ID: %2d\n", i++, x);
475                 }
476         }
477 }
478
479 /*
480  * AP CPU's call this to initialize themselves.
481  */
482 void
483 init_secondary(void)
484 {
485         struct pcpu *pc;
486         vm_offset_t addr;
487         int     gsel_tss;
488         int     x, myid;
489         u_int   cr0;
490
491         /* bootAP is set in start_ap() to our ID. */
492         myid = bootAP;
493
494         /* Get per-cpu data */
495         pc = &__pcpu[myid];
496
497         /* prime data page for it to use */
498         pcpu_init(pc, myid, sizeof(struct pcpu));
499         pc->pc_apic_id = cpu_apic_ids[myid];
500         pc->pc_prvspace = pc;
501         pc->pc_curthread = 0;
502
503         gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
504         gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
505
506         for (x = 0; x < NGDT; x++) {
507                 ssdtosd(&gdt_segs[x], &gdt[myid * NGDT + x].sd);
508         }
509
510         r_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
511         r_gdt.rd_base = (int) &gdt[myid * NGDT];
512         lgdt(&r_gdt);                   /* does magic intra-segment return */
513
514         lidt(&r_idt);
515
516         lldt(_default_ldt);
517         PCPU_SET(currentldt, _default_ldt);
518
519         gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
520         gdt[myid * NGDT + GPROC0_SEL].sd.sd_type = SDT_SYS386TSS;
521         PCPU_SET(common_tss.tss_esp0, 0); /* not used until after switch */
522         PCPU_SET(common_tss.tss_ss0, GSEL(GDATA_SEL, SEL_KPL));
523         PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
524         PCPU_SET(tss_gdt, &gdt[myid * NGDT + GPROC0_SEL].sd);
525         PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
526         ltr(gsel_tss);
527
528         PCPU_SET(fsgs_gdt, &gdt[myid * NGDT + GUFS_SEL].sd);
529
530         /*
531          * Set to a known state:
532          * Set by mpboot.s: CR0_PG, CR0_PE
533          * Set by cpu_setregs: CR0_NE, CR0_MP, CR0_TS, CR0_WP, CR0_AM
534          */
535         cr0 = rcr0();
536         cr0 &= ~(CR0_CD | CR0_NW | CR0_EM);
537         load_cr0(cr0);
538         CHECK_WRITE(0x38, 5);
539         
540         /* Disable local APIC just to be sure. */
541         lapic_disable();
542
543         /* signal our startup to the BSP. */
544         mp_naps++;
545         CHECK_WRITE(0x39, 6);
546
547         /* Spin until the BSP releases the AP's. */
548         while (!aps_ready)
549                 ia32_pause();
550
551         /* BSP may have changed PTD while we were waiting */
552         invltlb();
553         for (addr = 0; addr < NKPT * NBPDR - 1; addr += PAGE_SIZE)
554                 invlpg(addr);
555
556 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
557         lidt(&r_idt);
558 #endif
559
560         /* Initialize the PAT MSR if present. */
561         pmap_init_pat();
562
563         /* set up CPU registers and state */
564         cpu_setregs();
565
566         /* set up FPU state on the AP */
567         npxinit(__INITIAL_NPXCW__);
568
569         /* set up SSE registers */
570         enable_sse();
571
572 #ifdef PAE
573         /* Enable the PTE no-execute bit. */
574         if ((amd_feature & AMDID_NX) != 0) {
575                 uint64_t msr;
576
577                 msr = rdmsr(MSR_EFER) | EFER_NXE;
578                 wrmsr(MSR_EFER, msr);
579         }
580 #endif
581
582         /* A quick check from sanity claus */
583         if (PCPU_GET(apic_id) != lapic_id()) {
584                 printf("SMP: cpuid = %d\n", PCPU_GET(cpuid));
585                 printf("SMP: actual apic_id = %d\n", lapic_id());
586                 printf("SMP: correct apic_id = %d\n", PCPU_GET(apic_id));
587                 panic("cpuid mismatch! boom!!");
588         }
589
590         /* Initialize curthread. */
591         KASSERT(PCPU_GET(idlethread) != NULL, ("no idle thread"));
592         PCPU_SET(curthread, PCPU_GET(idlethread));
593
594         mtx_lock_spin(&ap_boot_mtx);
595
596         /* Init local apic for irq's */
597         lapic_setup(1);
598
599         /* Set memory range attributes for this CPU to match the BSP */
600         mem_range_AP_init();
601
602         smp_cpus++;
603
604         CTR1(KTR_SMP, "SMP: AP CPU #%d Launched", PCPU_GET(cpuid));
605         printf("SMP: AP CPU #%d Launched!\n", PCPU_GET(cpuid));
606
607         /* Determine if we are a logical CPU. */
608         if (logical_cpus > 1 && PCPU_GET(apic_id) % logical_cpus != 0)
609                 logical_cpus_mask |= PCPU_GET(cpumask);
610         
611         /* Determine if we are a hyperthread. */
612         if (hyperthreading_cpus > 1 &&
613             PCPU_GET(apic_id) % hyperthreading_cpus != 0)
614                 hyperthreading_cpus_mask |= PCPU_GET(cpumask);
615
616         /* Build our map of 'other' CPUs. */
617         PCPU_SET(other_cpus, all_cpus & ~PCPU_GET(cpumask));
618
619         if (bootverbose)
620                 lapic_dump("AP");
621
622         if (smp_cpus == mp_ncpus) {
623                 /* enable IPI's, tlb shootdown, freezes etc */
624                 atomic_store_rel_int(&smp_started, 1);
625                 smp_active = 1;  /* historic */
626         }
627
628         mtx_unlock_spin(&ap_boot_mtx);
629
630         /* wait until all the AP's are up */
631         while (smp_started == 0)
632                 ia32_pause();
633
634         /* enter the scheduler */
635         sched_throw(NULL);
636
637         panic("scheduler returned us to %s", __func__);
638         /* NOTREACHED */
639 }
640
641 /*******************************************************************
642  * local functions and data
643  */
644
645 /*
646  * We tell the I/O APIC code about all the CPUs we want to receive
647  * interrupts.  If we don't want certain CPUs to receive IRQs we
648  * can simply not tell the I/O APIC code about them in this function.
649  * We also do not tell it about the BSP since it tells itself about
650  * the BSP internally to work with UP kernels and on UP machines.
651  */
652 static void
653 set_interrupt_apic_ids(void)
654 {
655         u_int i, apic_id;
656
657         for (i = 0; i < MAXCPU; i++) {
658                 apic_id = cpu_apic_ids[i];
659                 if (apic_id == -1)
660                         continue;
661                 if (cpu_info[apic_id].cpu_bsp)
662                         continue;
663                 if (cpu_info[apic_id].cpu_disabled)
664                         continue;
665
666                 /* Don't let hyperthreads service interrupts. */
667                 if (hyperthreading_cpus > 1 &&
668                     apic_id % hyperthreading_cpus != 0)
669                         continue;
670
671                 intr_add_cpu(i);
672         }
673 }
674
675 /*
676  * Assign logical CPU IDs to local APICs.
677  */
678 static void
679 assign_cpu_ids(void)
680 {
681         u_int i;
682
683         /* Check for explicitly disabled CPUs. */
684         for (i = 0; i <= MAX_APIC_ID; i++) {
685                 if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp)
686                         continue;
687
688                 /* Don't use this CPU if it has been disabled by a tunable. */
689                 if (resource_disabled("lapic", i)) {
690                         cpu_info[i].cpu_disabled = 1;
691                         continue;
692                 }
693         }
694
695         /*
696          * Assign CPU IDs to local APIC IDs and disable any CPUs
697          * beyond MAXCPU.  CPU 0 has already been assigned to the BSP,
698          * so we only have to assign IDs for APs.
699          */
700         mp_ncpus = 1;
701         for (i = 0; i <= MAX_APIC_ID; i++) {
702                 if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp ||
703                     cpu_info[i].cpu_disabled)
704                         continue;
705
706                 if (mp_ncpus < MAXCPU) {
707                         cpu_apic_ids[mp_ncpus] = i;
708                         mp_ncpus++;
709                 } else
710                         cpu_info[i].cpu_disabled = 1;
711         }
712         KASSERT(mp_maxid >= mp_ncpus - 1,
713             ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid,
714             mp_ncpus));         
715 }
716
717 /*
718  * start each AP in our list
719  */
720 /* Lowest 1MB is already mapped: don't touch*/
721 #define TMPMAP_START 1
722 static int
723 start_all_aps(void)
724 {
725 #ifndef PC98
726         u_char mpbiosreason;
727 #endif
728         uintptr_t kptbase;
729         u_int32_t mpbioswarmvec;
730         int apic_id, cpu, i;
731
732         mtx_init(&ap_boot_mtx, "ap boot", NULL, MTX_SPIN);
733
734         /* install the AP 1st level boot code */
735         install_ap_tramp();
736
737         /* save the current value of the warm-start vector */
738         mpbioswarmvec = *((u_int32_t *) WARMBOOT_OFF);
739 #ifndef PC98
740         outb(CMOS_REG, BIOS_RESET);
741         mpbiosreason = inb(CMOS_DATA);
742 #endif
743
744         /* set up temporary P==V mapping for AP boot */
745         /* XXX this is a hack, we should boot the AP on its own stack/PTD */
746
747         kptbase = (uintptr_t)(void *)KPTphys;
748         for (i = TMPMAP_START; i < NKPT; i++)
749                 PTD[i] = (pd_entry_t)(PG_V | PG_RW |
750                     ((kptbase + i * PAGE_SIZE) & PG_FRAME));
751         invltlb();
752
753         /* start each AP */
754         for (cpu = 1; cpu < mp_ncpus; cpu++) {
755                 apic_id = cpu_apic_ids[cpu];
756
757                 /* allocate and set up a boot stack data page */
758                 bootstacks[cpu] = (char *)kmem_alloc(kernel_map, KSTACK_PAGES * PAGE_SIZE);
759
760                 /* setup a vector to our boot code */
761                 *((volatile u_short *) WARMBOOT_OFF) = WARMBOOT_TARGET;
762                 *((volatile u_short *) WARMBOOT_SEG) = (boot_address >> 4);
763 #ifndef PC98
764                 outb(CMOS_REG, BIOS_RESET);
765                 outb(CMOS_DATA, BIOS_WARM);     /* 'warm-start' */
766 #endif
767
768                 bootSTK = (char *)bootstacks[cpu] + KSTACK_PAGES * PAGE_SIZE - 4;
769                 bootAP = cpu;
770
771                 /* attempt to start the Application Processor */
772                 CHECK_INIT(99); /* setup checkpoints */
773                 if (!start_ap(apic_id)) {
774                         printf("AP #%d (PHY# %d) failed!\n", cpu, apic_id);
775                         CHECK_PRINT("trace");   /* show checkpoints */
776                         /* better panic as the AP may be running loose */
777                         printf("panic y/n? [y] ");
778                         if (cngetc() != 'n')
779                                 panic("bye-bye");
780                 }
781                 CHECK_PRINT("trace");           /* show checkpoints */
782
783                 all_cpus |= (1 << cpu);         /* record AP in CPU map */
784         }
785
786         /* build our map of 'other' CPUs */
787         PCPU_SET(other_cpus, all_cpus & ~PCPU_GET(cpumask));
788
789         /* restore the warmstart vector */
790         *(u_int32_t *) WARMBOOT_OFF = mpbioswarmvec;
791
792 #ifndef PC98
793         outb(CMOS_REG, BIOS_RESET);
794         outb(CMOS_DATA, mpbiosreason);
795 #endif
796
797         /* Undo V==P hack from above */
798         for (i = TMPMAP_START; i < NKPT; i++)
799                 PTD[i] = 0;
800         pmap_invalidate_range(kernel_pmap, 0, NKPT * NBPDR - 1);
801
802         /* number of APs actually started */
803         return mp_naps;
804 }
805
806 /*
807  * load the 1st level AP boot code into base memory.
808  */
809
810 /* targets for relocation */
811 extern void bigJump(void);
812 extern void bootCodeSeg(void);
813 extern void bootDataSeg(void);
814 extern void MPentry(void);
815 extern u_int MP_GDT;
816 extern u_int mp_gdtbase;
817
818 static void
819 install_ap_tramp(void)
820 {
821         int     x;
822         int     size = *(int *) ((u_long) & bootMP_size);
823         vm_offset_t va = boot_address + KERNBASE;
824         u_char *src = (u_char *) ((u_long) bootMP);
825         u_char *dst = (u_char *) va;
826         u_int   boot_base = (u_int) bootMP;
827         u_int8_t *dst8;
828         u_int16_t *dst16;
829         u_int32_t *dst32;
830
831         KASSERT (size <= PAGE_SIZE,
832             ("'size' do not fit into PAGE_SIZE, as expected."));
833         pmap_kenter(va, boot_address);
834         pmap_invalidate_page (kernel_pmap, va);
835         for (x = 0; x < size; ++x)
836                 *dst++ = *src++;
837
838         /*
839          * modify addresses in code we just moved to basemem. unfortunately we
840          * need fairly detailed info about mpboot.s for this to work.  changes
841          * to mpboot.s might require changes here.
842          */
843
844         /* boot code is located in KERNEL space */
845         dst = (u_char *) va;
846
847         /* modify the lgdt arg */
848         dst32 = (u_int32_t *) (dst + ((u_int) & mp_gdtbase - boot_base));
849         *dst32 = boot_address + ((u_int) & MP_GDT - boot_base);
850
851         /* modify the ljmp target for MPentry() */
852         dst32 = (u_int32_t *) (dst + ((u_int) bigJump - boot_base) + 1);
853         *dst32 = ((u_int) MPentry - KERNBASE);
854
855         /* modify the target for boot code segment */
856         dst16 = (u_int16_t *) (dst + ((u_int) bootCodeSeg - boot_base));
857         dst8 = (u_int8_t *) (dst16 + 1);
858         *dst16 = (u_int) boot_address & 0xffff;
859         *dst8 = ((u_int) boot_address >> 16) & 0xff;
860
861         /* modify the target for boot data segment */
862         dst16 = (u_int16_t *) (dst + ((u_int) bootDataSeg - boot_base));
863         dst8 = (u_int8_t *) (dst16 + 1);
864         *dst16 = (u_int) boot_address & 0xffff;
865         *dst8 = ((u_int) boot_address >> 16) & 0xff;
866 }
867
868 /*
869  * This function starts the AP (application processor) identified
870  * by the APIC ID 'physicalCpu'.  It does quite a "song and dance"
871  * to accomplish this.  This is necessary because of the nuances
872  * of the different hardware we might encounter.  It isn't pretty,
873  * but it seems to work.
874  */
875 static int
876 start_ap(int apic_id)
877 {
878         int vector, ms;
879         int cpus;
880
881         /* calculate the vector */
882         vector = (boot_address >> 12) & 0xff;
883
884         /* used as a watchpoint to signal AP startup */
885         cpus = mp_naps;
886
887         /*
888          * first we do an INIT/RESET IPI this INIT IPI might be run, reseting
889          * and running the target CPU. OR this INIT IPI might be latched (P5
890          * bug), CPU waiting for STARTUP IPI. OR this INIT IPI might be
891          * ignored.
892          */
893
894         /* do an INIT IPI: assert RESET */
895         lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
896             APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
897
898         /* wait for pending status end */
899         lapic_ipi_wait(-1);
900
901         /* do an INIT IPI: deassert RESET */
902         lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
903             APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
904
905         /* wait for pending status end */
906         DELAY(10000);           /* wait ~10mS */
907         lapic_ipi_wait(-1);
908
909         /*
910          * next we do a STARTUP IPI: the previous INIT IPI might still be
911          * latched, (P5 bug) this 1st STARTUP would then terminate
912          * immediately, and the previously started INIT IPI would continue. OR
913          * the previous INIT IPI has already run. and this STARTUP IPI will
914          * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
915          * will run.
916          */
917
918         /* do a STARTUP IPI */
919         lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
920             APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
921             vector, apic_id);
922         lapic_ipi_wait(-1);
923         DELAY(200);             /* wait ~200uS */
924
925         /*
926          * finally we do a 2nd STARTUP IPI: this 2nd STARTUP IPI should run IF
927          * the previous STARTUP IPI was cancelled by a latched INIT IPI. OR
928          * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
929          * recognized after hardware RESET or INIT IPI.
930          */
931
932         lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
933             APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
934             vector, apic_id);
935         lapic_ipi_wait(-1);
936         DELAY(200);             /* wait ~200uS */
937
938         /* Wait up to 5 seconds for it to start. */
939         for (ms = 0; ms < 5000; ms++) {
940                 if (mp_naps > cpus)
941                         return 1;       /* return SUCCESS */
942                 DELAY(1000);
943         }
944         return 0;               /* return FAILURE */
945 }
946
947 #ifdef COUNT_XINVLTLB_HITS
948 u_int xhits_gbl[MAXCPU];
949 u_int xhits_pg[MAXCPU];
950 u_int xhits_rng[MAXCPU];
951 SYSCTL_NODE(_debug, OID_AUTO, xhits, CTLFLAG_RW, 0, "");
952 SYSCTL_OPAQUE(_debug_xhits, OID_AUTO, global, CTLFLAG_RW, &xhits_gbl,
953     sizeof(xhits_gbl), "IU", "");
954 SYSCTL_OPAQUE(_debug_xhits, OID_AUTO, page, CTLFLAG_RW, &xhits_pg,
955     sizeof(xhits_pg), "IU", "");
956 SYSCTL_OPAQUE(_debug_xhits, OID_AUTO, range, CTLFLAG_RW, &xhits_rng,
957     sizeof(xhits_rng), "IU", "");
958
959 u_int ipi_global;
960 u_int ipi_page;
961 u_int ipi_range;
962 u_int ipi_range_size;
963 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_global, CTLFLAG_RW, &ipi_global, 0, "");
964 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_page, CTLFLAG_RW, &ipi_page, 0, "");
965 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_range, CTLFLAG_RW, &ipi_range, 0, "");
966 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_range_size, CTLFLAG_RW, &ipi_range_size,
967     0, "");
968
969 u_int ipi_masked_global;
970 u_int ipi_masked_page;
971 u_int ipi_masked_range;
972 u_int ipi_masked_range_size;
973 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_masked_global, CTLFLAG_RW,
974     &ipi_masked_global, 0, "");
975 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_masked_page, CTLFLAG_RW,
976     &ipi_masked_page, 0, "");
977 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_masked_range, CTLFLAG_RW,
978     &ipi_masked_range, 0, "");
979 SYSCTL_INT(_debug_xhits, OID_AUTO, ipi_masked_range_size, CTLFLAG_RW,
980     &ipi_masked_range_size, 0, "");
981 #endif /* COUNT_XINVLTLB_HITS */
982
983 /*
984  * Flush the TLB on all other CPU's
985  */
986 static void
987 smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2)
988 {
989         u_int ncpu;
990
991         ncpu = mp_ncpus - 1;    /* does not shootdown self */
992         if (ncpu < 1)
993                 return;         /* no other cpus */
994         if (!(read_eflags() & PSL_I))
995                 panic("%s: interrupts disabled", __func__);
996         mtx_lock_spin(&smp_ipi_mtx);
997         smp_tlb_addr1 = addr1;
998         smp_tlb_addr2 = addr2;
999         atomic_store_rel_int(&smp_tlb_wait, 0);
1000         ipi_all_but_self(vector);
1001         while (smp_tlb_wait < ncpu)
1002                 ia32_pause();
1003         mtx_unlock_spin(&smp_ipi_mtx);
1004 }
1005
1006 static void
1007 smp_targeted_tlb_shootdown(u_int mask, u_int vector, vm_offset_t addr1, vm_offset_t addr2)
1008 {
1009         int ncpu, othercpus;
1010
1011         othercpus = mp_ncpus - 1;
1012         if (mask == (u_int)-1) {
1013                 ncpu = othercpus;
1014                 if (ncpu < 1)
1015                         return;
1016         } else {
1017                 mask &= ~PCPU_GET(cpumask);
1018                 if (mask == 0)
1019                         return;
1020                 ncpu = bitcount32(mask);
1021                 if (ncpu > othercpus) {
1022                         /* XXX this should be a panic offence */
1023                         printf("SMP: tlb shootdown to %d other cpus (only have %d)\n",
1024                             ncpu, othercpus);
1025                         ncpu = othercpus;
1026                 }
1027                 /* XXX should be a panic, implied by mask == 0 above */
1028                 if (ncpu < 1)
1029                         return;
1030         }
1031         if (!(read_eflags() & PSL_I))
1032                 panic("%s: interrupts disabled", __func__);
1033         mtx_lock_spin(&smp_ipi_mtx);
1034         smp_tlb_addr1 = addr1;
1035         smp_tlb_addr2 = addr2;
1036         atomic_store_rel_int(&smp_tlb_wait, 0);
1037         if (mask == (u_int)-1)
1038                 ipi_all_but_self(vector);
1039         else
1040                 ipi_selected(mask, vector);
1041         while (smp_tlb_wait < ncpu)
1042                 ia32_pause();
1043         mtx_unlock_spin(&smp_ipi_mtx);
1044 }
1045
1046 void
1047 smp_cache_flush(void)
1048 {
1049
1050         if (smp_started)
1051                 smp_tlb_shootdown(IPI_INVLCACHE, 0, 0);
1052 }
1053
1054 void
1055 smp_invltlb(void)
1056 {
1057
1058         if (smp_started) {
1059                 smp_tlb_shootdown(IPI_INVLTLB, 0, 0);
1060 #ifdef COUNT_XINVLTLB_HITS
1061                 ipi_global++;
1062 #endif
1063         }
1064 }
1065
1066 void
1067 smp_invlpg(vm_offset_t addr)
1068 {
1069
1070         if (smp_started) {
1071                 smp_tlb_shootdown(IPI_INVLPG, addr, 0);
1072 #ifdef COUNT_XINVLTLB_HITS
1073                 ipi_page++;
1074 #endif
1075         }
1076 }
1077
1078 void
1079 smp_invlpg_range(vm_offset_t addr1, vm_offset_t addr2)
1080 {
1081
1082         if (smp_started) {
1083                 smp_tlb_shootdown(IPI_INVLRNG, addr1, addr2);
1084 #ifdef COUNT_XINVLTLB_HITS
1085                 ipi_range++;
1086                 ipi_range_size += (addr2 - addr1) / PAGE_SIZE;
1087 #endif
1088         }
1089 }
1090
1091 void
1092 smp_masked_invltlb(u_int mask)
1093 {
1094
1095         if (smp_started) {
1096                 smp_targeted_tlb_shootdown(mask, IPI_INVLTLB, 0, 0);
1097 #ifdef COUNT_XINVLTLB_HITS
1098                 ipi_masked_global++;
1099 #endif
1100         }
1101 }
1102
1103 void
1104 smp_masked_invlpg(u_int mask, vm_offset_t addr)
1105 {
1106
1107         if (smp_started) {
1108                 smp_targeted_tlb_shootdown(mask, IPI_INVLPG, addr, 0);
1109 #ifdef COUNT_XINVLTLB_HITS
1110                 ipi_masked_page++;
1111 #endif
1112         }
1113 }
1114
1115 void
1116 smp_masked_invlpg_range(u_int mask, vm_offset_t addr1, vm_offset_t addr2)
1117 {
1118
1119         if (smp_started) {
1120                 smp_targeted_tlb_shootdown(mask, IPI_INVLRNG, addr1, addr2);
1121 #ifdef COUNT_XINVLTLB_HITS
1122                 ipi_masked_range++;
1123                 ipi_masked_range_size += (addr2 - addr1) / PAGE_SIZE;
1124 #endif
1125         }
1126 }
1127
1128 void
1129 ipi_bitmap_handler(struct trapframe frame)
1130 {
1131         int cpu = PCPU_GET(cpuid);
1132         u_int ipi_bitmap;
1133
1134         ipi_bitmap = atomic_readandclear_int(&cpu_ipi_pending[cpu]);
1135
1136         if (ipi_bitmap & (1 << IPI_PREEMPT)) {
1137 #ifdef COUNT_IPIS
1138                 (*ipi_preempt_counts[cpu])++;
1139 #endif
1140                 sched_preempt(curthread);
1141         }
1142
1143         if (ipi_bitmap & (1 << IPI_AST)) {
1144 #ifdef COUNT_IPIS
1145                 (*ipi_ast_counts[cpu])++;
1146 #endif
1147                 /* Nothing to do for AST */
1148         }
1149 }
1150
1151 /*
1152  * send an IPI to a set of cpus.
1153  */
1154 void
1155 ipi_selected(u_int32_t cpus, u_int ipi)
1156 {
1157         int cpu;
1158         u_int bitmap = 0;
1159         u_int old_pending;
1160         u_int new_pending;
1161
1162         if (IPI_IS_BITMAPED(ipi)) { 
1163                 bitmap = 1 << ipi;
1164                 ipi = IPI_BITMAP_VECTOR;
1165         }
1166
1167 #ifdef STOP_NMI
1168         if (ipi == IPI_STOP && stop_cpus_with_nmi) {
1169                 ipi_nmi_selected(cpus);
1170                 return;
1171         }
1172 #endif
1173         CTR3(KTR_SMP, "%s: cpus: %x ipi: %x", __func__, cpus, ipi);
1174         while ((cpu = ffs(cpus)) != 0) {
1175                 cpu--;
1176                 cpus &= ~(1 << cpu);
1177
1178                 KASSERT(cpu_apic_ids[cpu] != -1,
1179                     ("IPI to non-existent CPU %d", cpu));
1180
1181                 if (bitmap) {
1182                         do {
1183                                 old_pending = cpu_ipi_pending[cpu];
1184                                 new_pending = old_pending | bitmap;
1185                         } while  (!atomic_cmpset_int(&cpu_ipi_pending[cpu],old_pending, new_pending));  
1186
1187                         if (old_pending)
1188                                 continue;
1189                 }
1190
1191                 lapic_ipi_vectored(ipi, cpu_apic_ids[cpu]);
1192         }
1193
1194 }
1195
1196 /*
1197  * send an IPI to all CPUs EXCEPT myself
1198  */
1199 void
1200 ipi_all_but_self(u_int ipi)
1201 {
1202
1203         if (IPI_IS_BITMAPED(ipi) || (ipi == IPI_STOP && stop_cpus_with_nmi)) {
1204                 ipi_selected(PCPU_GET(other_cpus), ipi);
1205                 return;
1206         }
1207         CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
1208         lapic_ipi_vectored(ipi, APIC_IPI_DEST_OTHERS);
1209 }
1210
1211 #ifdef STOP_NMI
1212 /*
1213  * send NMI IPI to selected CPUs
1214  */
1215
1216 #define BEFORE_SPIN     1000000
1217
1218 void
1219 ipi_nmi_selected(u_int32_t cpus)
1220 {
1221         int cpu;
1222         register_t icrlo;
1223
1224         icrlo = APIC_DELMODE_NMI | APIC_DESTMODE_PHY | APIC_LEVEL_ASSERT 
1225                 | APIC_TRIGMOD_EDGE; 
1226         
1227         CTR2(KTR_SMP, "%s: cpus: %x nmi", __func__, cpus);
1228
1229         atomic_set_int(&ipi_nmi_pending, cpus);
1230
1231         while ((cpu = ffs(cpus)) != 0) {
1232                 cpu--;
1233                 cpus &= ~(1 << cpu);
1234
1235                 KASSERT(cpu_apic_ids[cpu] != -1,
1236                     ("IPI NMI to non-existent CPU %d", cpu));
1237                 
1238                 /* Wait for an earlier IPI to finish. */
1239                 if (!lapic_ipi_wait(BEFORE_SPIN))
1240                         panic("ipi_nmi_selected: previous IPI has not cleared");
1241
1242                 lapic_ipi_raw(icrlo, cpu_apic_ids[cpu]);
1243         }
1244 }
1245
1246 int
1247 ipi_nmi_handler(void)
1248 {
1249         int cpumask = PCPU_GET(cpumask);
1250
1251         if (!(ipi_nmi_pending & cpumask))
1252                 return 1;
1253
1254         atomic_clear_int(&ipi_nmi_pending, cpumask);
1255         cpustop_handler();
1256         return 0;
1257 }
1258
1259 #endif /* STOP_NMI */
1260
1261 /*
1262  * Handle an IPI_STOP by saving our current context and spinning until we
1263  * are resumed.
1264  */
1265 void
1266 cpustop_handler(void)
1267 {
1268         int cpu = PCPU_GET(cpuid);
1269         int cpumask = PCPU_GET(cpumask);
1270
1271         savectx(&stoppcbs[cpu]);
1272
1273         /* Indicate that we are stopped */
1274         atomic_set_int(&stopped_cpus, cpumask);
1275
1276         /* Wait for restart */
1277         while (!(started_cpus & cpumask))
1278             ia32_pause();
1279
1280         atomic_clear_int(&started_cpus, cpumask);
1281         atomic_clear_int(&stopped_cpus, cpumask);
1282
1283         if (cpu == 0 && cpustop_restartfunc != NULL) {
1284                 cpustop_restartfunc();
1285                 cpustop_restartfunc = NULL;
1286         }
1287 }
1288
1289 /*
1290  * This is called once the rest of the system is up and running and we're
1291  * ready to let the AP's out of the pen.
1292  */
1293 static void
1294 release_aps(void *dummy __unused)
1295 {
1296
1297         if (mp_ncpus == 1) 
1298                 return;
1299         atomic_store_rel_int(&aps_ready, 1);
1300         while (smp_started == 0)
1301                 ia32_pause();
1302 }
1303 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, release_aps, NULL);
1304
1305 static int
1306 sysctl_hlt_cpus(SYSCTL_HANDLER_ARGS)
1307 {
1308         u_int mask;
1309         int error;
1310
1311         mask = hlt_cpus_mask;
1312         error = sysctl_handle_int(oidp, &mask, 0, req);
1313         if (error || !req->newptr)
1314                 return (error);
1315
1316         if (logical_cpus_mask != 0 &&
1317             (mask & logical_cpus_mask) == logical_cpus_mask)
1318                 hlt_logical_cpus = 1;
1319         else
1320                 hlt_logical_cpus = 0;
1321
1322         if (! hyperthreading_allowed)
1323                 mask |= hyperthreading_cpus_mask;
1324
1325         if ((mask & all_cpus) == all_cpus)
1326                 mask &= ~(1<<0);
1327         hlt_cpus_mask = mask;
1328         return (error);
1329 }
1330 SYSCTL_PROC(_machdep, OID_AUTO, hlt_cpus, CTLTYPE_INT|CTLFLAG_RW,
1331     0, 0, sysctl_hlt_cpus, "IU",
1332     "Bitmap of CPUs to halt.  101 (binary) will halt CPUs 0 and 2.");
1333
1334 static int
1335 sysctl_hlt_logical_cpus(SYSCTL_HANDLER_ARGS)
1336 {
1337         int disable, error;
1338
1339         disable = hlt_logical_cpus;
1340         error = sysctl_handle_int(oidp, &disable, 0, req);
1341         if (error || !req->newptr)
1342                 return (error);
1343
1344         if (disable)
1345                 hlt_cpus_mask |= logical_cpus_mask;
1346         else
1347                 hlt_cpus_mask &= ~logical_cpus_mask;
1348
1349         if (! hyperthreading_allowed)
1350                 hlt_cpus_mask |= hyperthreading_cpus_mask;
1351
1352         if ((hlt_cpus_mask & all_cpus) == all_cpus)
1353                 hlt_cpus_mask &= ~(1<<0);
1354
1355         hlt_logical_cpus = disable;
1356         return (error);
1357 }
1358
1359 static int
1360 sysctl_hyperthreading_allowed(SYSCTL_HANDLER_ARGS)
1361 {
1362         int allowed, error;
1363
1364         allowed = hyperthreading_allowed;
1365         error = sysctl_handle_int(oidp, &allowed, 0, req);
1366         if (error || !req->newptr)
1367                 return (error);
1368
1369         if (allowed)
1370                 hlt_cpus_mask &= ~hyperthreading_cpus_mask;
1371         else
1372                 hlt_cpus_mask |= hyperthreading_cpus_mask;
1373
1374         if (logical_cpus_mask != 0 &&
1375             (hlt_cpus_mask & logical_cpus_mask) == logical_cpus_mask)
1376                 hlt_logical_cpus = 1;
1377         else
1378                 hlt_logical_cpus = 0;
1379
1380         if ((hlt_cpus_mask & all_cpus) == all_cpus)
1381                 hlt_cpus_mask &= ~(1<<0);
1382
1383         hyperthreading_allowed = allowed;
1384         return (error);
1385 }
1386
1387 static void
1388 cpu_hlt_setup(void *dummy __unused)
1389 {
1390
1391         if (logical_cpus_mask != 0) {
1392                 TUNABLE_INT_FETCH("machdep.hlt_logical_cpus",
1393                     &hlt_logical_cpus);
1394                 sysctl_ctx_init(&logical_cpu_clist);
1395                 SYSCTL_ADD_PROC(&logical_cpu_clist,
1396                     SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
1397                     "hlt_logical_cpus", CTLTYPE_INT|CTLFLAG_RW, 0, 0,
1398                     sysctl_hlt_logical_cpus, "IU", "");
1399                 SYSCTL_ADD_UINT(&logical_cpu_clist,
1400                     SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
1401                     "logical_cpus_mask", CTLTYPE_INT|CTLFLAG_RD,
1402                     &logical_cpus_mask, 0, "");
1403
1404                 if (hlt_logical_cpus)
1405                         hlt_cpus_mask |= logical_cpus_mask;
1406
1407                 /*
1408                  * If necessary for security purposes, force
1409                  * hyperthreading off, regardless of the value
1410                  * of hlt_logical_cpus.
1411                  */
1412                 if (hyperthreading_cpus_mask) {
1413                         TUNABLE_INT_FETCH("machdep.hyperthreading_allowed",
1414                             &hyperthreading_allowed);
1415                         SYSCTL_ADD_PROC(&logical_cpu_clist,
1416                             SYSCTL_STATIC_CHILDREN(_machdep), OID_AUTO,
1417                             "hyperthreading_allowed", CTLTYPE_INT|CTLFLAG_RW,
1418                             0, 0, sysctl_hyperthreading_allowed, "IU", "");
1419                         if (! hyperthreading_allowed)
1420                                 hlt_cpus_mask |= hyperthreading_cpus_mask;
1421                 }
1422         }
1423 }
1424 SYSINIT(cpu_hlt, SI_SUB_SMP, SI_ORDER_ANY, cpu_hlt_setup, NULL);
1425
1426 int
1427 mp_grab_cpu_hlt(void)
1428 {
1429         u_int mask = PCPU_GET(cpumask);
1430 #ifdef MP_WATCHDOG
1431         u_int cpuid = PCPU_GET(cpuid);
1432 #endif
1433         int retval;
1434
1435 #ifdef MP_WATCHDOG
1436         ap_watchdog(cpuid);
1437 #endif
1438
1439         retval = mask & hlt_cpus_mask;
1440         while (mask & hlt_cpus_mask)
1441                 __asm __volatile("sti; hlt" : : : "memory");
1442         return (retval);
1443 }
1444
1445 #ifdef COUNT_IPIS
1446 /*
1447  * Setup interrupt counters for IPI handlers.
1448  */
1449 static void
1450 mp_ipi_intrcnt(void *dummy)
1451 {
1452         char buf[64];
1453         int i;
1454
1455         for (i = 0; i < mp_maxid; i++) {
1456                 if (CPU_ABSENT(i))
1457                         continue;
1458                 snprintf(buf, sizeof(buf), "cpu%d: invltlb", i);
1459                 intrcnt_add(buf, &ipi_invltlb_counts[i]);
1460                 snprintf(buf, sizeof(buf), "cpu%d: invlrng", i);
1461                 intrcnt_add(buf, &ipi_invlrng_counts[i]);
1462                 snprintf(buf, sizeof(buf), "cpu%d: invlpg", i);
1463                 intrcnt_add(buf, &ipi_invlpg_counts[i]);
1464                 snprintf(buf, sizeof(buf), "cpu%d: preempt", i);
1465                 intrcnt_add(buf, &ipi_preempt_counts[i]);
1466                 snprintf(buf, sizeof(buf), "cpu%d: ast", i);
1467                 intrcnt_add(buf, &ipi_ast_counts[i]);
1468                 snprintf(buf, sizeof(buf), "cpu%d: rendezvous", i);
1469                 intrcnt_add(buf, &ipi_rendezvous_counts[i]);
1470                 snprintf(buf, sizeof(buf), "cpu%d: lazypmap", i);
1471                 intrcnt_add(buf, &ipi_lazypmap_counts[i]);
1472         }               
1473 }
1474 SYSINIT(mp_ipi_intrcnt, SI_SUB_INTR, SI_ORDER_MIDDLE, mp_ipi_intrcnt, NULL);
1475 #endif