#include <asm/hw_irq.h>
#include <asm/numa.h>
+#include <mach_wakecpu.h>
+#include <smpboot_hooks.h>
+
/* Set when the idlers are all forked */
int smp_threads_ready;
#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
#endif
-/*
- * The bootstrap kernel entry code has set these up. Save them for
- * a given CPU
- */
-
-static void __cpuinit smp_store_cpu_info(int id)
-{
- struct cpuinfo_x86 *c = &cpu_data(id);
-
- *c = boot_cpu_data;
- c->cpu_index = id;
- identify_cpu(c);
- print_cpu_info(c);
-}
-
-static inline void wait_for_init_deassert(atomic_t *deassert)
-{
- while (!atomic_read(deassert))
- cpu_relax();
- return;
-}
-
static atomic_t init_deasserted __cpuinitdata;
/*
*/
spin_unlock(&vector_lock);
cpu_set(smp_processor_id(), cpu_online_map);
- per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
-
unlock_ipi_call_lock();
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+
setup_secondary_clock();
+ wmb();
cpu_idle();
}
extern void (*initial_code)(void);
#ifdef APIC_DEBUG
-static void inquire_remote_apic(int apicid)
+static void __inquire_remote_apic(int apicid)
{
unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
char *names[] = { "ID", "VERSION", "SPIV" };
unsigned long send_status, accept_status = 0;
int maxlvt, num_starts, j;
+ /*
+ * Be paranoid about clearing APIC errors.
+ */
+ if (APIC_INTEGRATED(apic_version[phys_apicid])) {
+ apic_read_around(APIC_SPIV);
+ apic_write(APIC_ESR, 0);
+ apic_read(APIC_ESR);
+ }
+
Dprintk("Asserting INIT.\n");
/*
mb();
atomic_set(&init_deasserted, 1);
- num_starts = 2;
+ if (APIC_INTEGRATED(apic_version[phys_apicid]))
+ num_starts = 2;
+ else
+ num_starts = 0;
/*
* Paravirt / VMI wants a startup IPI hook here to set up the
Dprintk("Setting warm reset code and vector.\n");
- CMOS_WRITE(0xa, 0xf);
- local_flush_tlb();
- Dprintk("1.\n");
- *((volatile unsigned short *) phys_to_virt(0x469)) = start_rip >> 4;
- Dprintk("2.\n");
- *((volatile unsigned short *) phys_to_virt(0x467)) = start_rip & 0xf;
- Dprintk("3.\n");
-
+ smpboot_setup_warm_reset_vector(start_rip);
/*
* Be paranoid about clearing APIC errors.
*/
if (cpu_isset(cpu, cpu_callin_map)) {
/* number CPUs logically, starting from 1 (BSP is 0) */
Dprintk("CPU has booted.\n");
+ printk(KERN_INFO "CPU%d: ", cpu);
+ print_cpu_info(&cpu_data(cpu));
} else {
boot_error = 1;
if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
cycles_t cacheflush_time;
unsigned long cache_decay_ticks;
-/*
- * Cleanup possible dangling ends...
- */
-static __cpuinit void smp_cleanup_boot(void)
-{
- /*
- * Paranoid: Set warm reset code and vector here back
- * to default values.
- */
- CMOS_WRITE(0, 0xf);
-
- /*
- * Reset trampoline flag
- */
- *((volatile int *) phys_to_virt(0x467)) = 0;
-}
-
/*
* Fall back to non SMP mode after errors.
*
*/
setup_boot_clock();
+ printk(KERN_INFO "CPU%d: ", 0);
+ print_cpu_info(&cpu_data(0));
}
/*
return err;
}
+extern void impress_friends(void);
+extern void smp_checks(void);
+
/*
* Finish the SMP boot.
*/
void __init native_smp_cpus_done(unsigned int max_cpus)
{
- smp_cleanup_boot();
+ smpboot_restore_warm_reset_vector();
+
+ Dprintk("Boot done.\n");
+
+ impress_friends();
+ smp_checks();
setup_ioapic_dest();
check_nmi_watchdog();
}