+ /* Ignore this if the current processor is not the starter */
+ if (cpu_number() != psip->starter_cpu) {
+ return;
+ }
+
+ DBG("start_cpu(%p) about to start cpu %d, lapic %d\n",
+ arg, psip->target_cpu, psip->target_lapic);
+
+ KERNEL_DEBUG_CONSTANT(
+ TRACE_MP_CPU_START | DBG_FUNC_START,
+ psip->target_cpu,
+ psip->target_lapic, 0, 0, 0);
+
+ i386_start_cpu(psip->target_lapic, psip->target_cpu);
+
+#ifdef POSTCODE_DELAY
+ /* Wait much longer if postcodes are displayed for a delay period. */
+ i *= 10000;
+#endif
+ DBG("start_cpu(%p) about to wait for cpu %d\n",
+ arg, psip->target_cpu);
+
+ mp_wait_for_cpu_up(psip->target_cpu, i * 100, 100);
+
+ KERNEL_DEBUG_CONSTANT(
+ TRACE_MP_CPU_START | DBG_FUNC_END,
+ psip->target_cpu,
+ cpu_datap(psip->target_cpu)->cpu_running, 0, 0, 0);
+
+ if (TSC_sync_margin &&
+ cpu_datap(psip->target_cpu)->cpu_running) {
+ /*
+ * Compare the TSC from the started processor with ours.
+ * Report and log/panic if it diverges by more than
+ * TSC_sync_margin (TSC_SYNC_MARGIN) ticks. This margin
+ * can be overriden by boot-arg (with 0 meaning no checking).
+ */
+ uint64_t tsc_starter;
+ int64_t tsc_delta;
+ atomic_decl(&tsc_entry_barrier, 1);
+ while (tsc_entry_barrier != 0) {
+ ; /* spin for both processors at barrier */
+ }
+ tsc_starter = rdtsc64();
+ atomic_decl(&tsc_exit_barrier, 1);
+ while (tsc_exit_barrier != 0) {
+ ; /* spin for target to store its TSC */
+ }
+ tsc_delta = tsc_target - tsc_starter;
+ kprintf("TSC sync for cpu %d: 0x%016llx delta 0x%llx (%lld)\n",
+ psip->target_cpu, tsc_target, tsc_delta, tsc_delta);
+#if DEBUG || DEVELOPMENT
+ /*
+ * Stash the delta for inspection later, since we can no
+ * longer print/log it with interrupts disabled.
+ */
+ cpu_datap(psip->target_cpu)->tsc_sync_delta = tsc_delta;
+#endif
+ if (ABS(tsc_delta) > (int64_t) TSC_sync_margin) {
+#if DEBUG
+ panic(
+#else
+ kprintf(
+#endif
+ "Unsynchronized TSC for cpu %d: "
+ "0x%016llx, delta 0x%llx\n",
+ psip->target_cpu, tsc_target, tsc_delta);
+ }
+ }
+}
+
+kern_return_t
+intel_startCPU(
+ int slot_num)
+{
+ int lapic = cpu_to_lapic[slot_num];
+ boolean_t istate;
+
+ assert(lapic != -1);
+
+ DBGLOG_CPU_INIT(slot_num);
+
+ DBG("intel_startCPU(%d) lapic_id=%d\n", slot_num, lapic);
+ DBG("IdlePTD(%p): 0x%x\n", &IdlePTD, (int) (uintptr_t)IdlePTD);