static void smp_halt(void) { int cpuid = safe_smp_processor_id(); static int first_entry = 1; if (reboot_force) return; if (first_entry) { first_entry = 0; smp_call_function((void *)machine_restart, NULL, 1, 0); } smp_stop_cpu(); /* AP calling this. Just halt */ if (cpuid != boot_cpu_id) { for (;;) asm("hlt"); } /* Wait for all other CPUs to have run smp_stop_cpu */ while (!cpus_empty(cpu_online_map)) rep_nop(); }
/* TSC based delay: */ static void delay_tsc(unsigned long loops) { unsigned long bclock, now; int cpu; preempt_disable(); cpu = smp_processor_id(); rdtscl(bclock); for (;;) { rdtscl(now); if ((now - bclock) >= loops) break; /* Allow RT tasks to run */ preempt_enable(); rep_nop(); preempt_disable(); /* * It is possible that we moved to another CPU, and * since TSC's are per-cpu we need to calculate * that. The delay must guarantee that we wait "at * least" the amount of time. Being moved to another * CPU could make the wait longer but we just need to * make sure we waited long enough. Rebalance the * counter for this CPU. */ if (unlikely(cpu != smp_processor_id())) { loops -= (now - bclock); cpu = smp_processor_id(); rdtscl(bclock); } } preempt_enable(); }
static void es7000_spin(int n) { int i = 0; while (i++ < n) rep_nop(); }
/* * Activate a secondary processor. */ static void __init start_secondary(void *unused) { /* * Dont put anything before smp_callin(), SMP * booting is too fragile that we want to limit the * things done here to the most necessary things. */ cpu_init(); smp_callin(); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); setup_secondary_APIC_clock(); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); enable_NMI_through_LVT0(NULL); enable_8259A_irq(0); } enable_APIC_timer(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. */ local_flush_tlb(); cpu_set(smp_processor_id(), cpu_online_map); /* We can take interrupts now: we're officially "up". */ local_irq_enable(); wmb(); cpu_idle(); }
/* TSC based delay: */ static notrace void delay_tsc(unsigned long loops) { unsigned long bclock, now; rdtscl(bclock); do { rep_nop(); rdtscl(now); } while ((now-bclock) < loops); }
void __delay(unsigned long loops) { unsigned bclock, now; rdtscl(bclock); do { rep_nop(); rdtscl(now); } while((now-bclock) < loops); }
/* TSC based delay: */ static void delay_tsc(unsigned long loops) { unsigned long bclock, now; preempt_disable(); /* TSC's are per-cpu */ rdtscl(bclock); do { rep_nop(); rdtscl(now); } while ((now-bclock) < loops); preempt_enable(); }
static void delay_hpet(unsigned long loops) { unsigned long hpet_start, hpet_end; unsigned long eax; /* loops is the number of cpu cycles. Convert it to hpet clocks */ ASM_MUL64_REG(eax, loops, tsc_hpet_quotient, loops); hpet_start = hpet_readl(HPET_COUNTER); do { rep_nop(); hpet_end = hpet_readl(HPET_COUNTER); } while ((hpet_end - hpet_start) < (loops)); }
void ndelay(const unsigned long nsec) { struct timeval now, end; gettimeofday(&end, NULL); end.tv_usec += (nsec + 999) / 1000; while (end.tv_usec > 1000000) { end.tv_usec -= 1000000; end.tv_sec++; } do { rep_nop(); gettimeofday(&now, NULL); } while (now.tv_sec == end.tv_sec ? now.tv_usec < end.tv_usec : now.tv_sec < end.tv_sec); }
/* * Activate a secondary processor. */ void __init start_secondary(void) { /* * Dont put anything before smp_callin(), SMP * booting is too fragile that we want to limit the * things done here to the most necessary things. */ cpu_init(); smp_callin(); /* otherwise gcc will move up the smp_processor_id before the cpu_init */ barrier(); Dprintk("cpu %d: waiting for commence\n", smp_processor_id()); while (!cpu_isset(smp_processor_id(), smp_commenced_mask)) rep_nop(); Dprintk("cpu %d: setting up apic clock\n", smp_processor_id()); setup_secondary_APIC_clock(); Dprintk("cpu %d: enabling apic timer\n", smp_processor_id()); if (nmi_watchdog == NMI_IO_APIC) { disable_8259A_irq(0); enable_NMI_through_LVT0(NULL); enable_8259A_irq(0); } enable_APIC_timer(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. */ local_flush_tlb(); Dprintk("cpu %d eSetting cpu_online_map\n", smp_processor_id()); cpu_set(smp_processor_id(), cpu_online_map); wmb(); cpu_idle(); }
static void __init smp_callin(void) { int cpuid, phys_id; unsigned long timeout; /* * If waken up by an INIT in an 82489DX configuration * we may get here before an INIT-deassert IPI reaches * our local APIC. We have to wait for the IPI or we'll * lock up on an APIC access. */ wait_for_init_deassert(&init_deasserted); /* * (This works even if the APIC is not enabled.) */ phys_id = GET_APIC_ID(apic_read(APIC_ID)); cpuid = smp_processor_id(); if (cpu_isset(cpuid, cpu_callin_map)) { printk("huh, phys CPU#%d, CPU#%d already present??\n", phys_id, cpuid); BUG(); } Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id); /* * STARTUP IPIs are fragile beasts as they might sometimes * trigger some glue motherboard logic. Complete APIC bus * silence for 1 second, this overestimates the time the * boot CPU is spending to send the up to 2 STARTUP IPIs * by a factor of two. This should be enough. */ /* * Waiting 2s total for startup (udelay is not yet working) */ timeout = jiffies + 2*HZ; while (time_before(jiffies, timeout)) { /* * Has the boot CPU finished it's STARTUP sequence? */ if (cpu_isset(cpuid, cpu_callout_map)) break; rep_nop(); } if (!time_before(jiffies, timeout)) { printk("BUG: CPU%d started up but did not get a callout!\n", cpuid); BUG(); } /* * the boot CPU has finished the init stage and is spinning * on callin_map until we finish. We are free to set up this * CPU, first the APIC. (this is probably redundant on most * boards) */ Dprintk("CALLIN, before setup_local_APIC().\n"); smp_callin_clear_local_apic(); setup_local_APIC(); map_cpu_to_logical_apicid(); /* * Get our bogomips. */ calibrate_delay(); Dprintk("Stack at about %p\n",&cpuid); /* * Save our processor parameters */ smp_store_cpu_info(cpuid); disable_APIC_timer(); /* * Allow the master to continue. */ cpu_set(cpuid, cpu_callin_map); /* * Synchronize the TSC with the BP */ if (cpu_has_tsc && cpu_khz) synchronize_tsc_ap(); }