#include <linux/irq.h>
#include <linux/bootmem.h>
#include <linux/thread_info.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
-char phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+/* Package ID of each logical CPU */
+u8 phys_proc_id[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+EXPORT_SYMBOL(phys_proc_id);
/* Bitmask of currently online CPUs */
cpumask_t cpu_online_map;
-/* which logical CPU number maps to which CPU (physical APIC ID) */
-volatile char x86_cpu_to_apicid[NR_CPUS];
-
-static cpumask_t cpu_callin_map;
+cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map;
static cpumask_t smp_commenced_mask;
/* Set when the idlers are all forked */
int smp_threads_ready;
-char cpu_sibling_map[NR_CPUS] __cacheline_aligned;
+cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
/*
* Trampoline 80x86 program as an array.
extern volatile unsigned long init_rsp;
extern void (*initial_code)(void);
-static struct task_struct * __init fork_by_hand(void)
-{
- struct pt_regs regs;
- /*
- * don't care about the eip and regs settings since
- * we'll never reschedule the forked task.
- */
- return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL);
-}
-
#if APIC_DEBUG
static inline void inquire_remote_apic(int apicid)
{
* We can't use kernel_thread since we must avoid to
* reschedule the child.
*/
- idle = fork_by_hand();
+ idle = fork_idle(cpu);
if (IS_ERR(idle))
panic("failed fork for CPU %d", cpu);
- wake_up_forked_process(idle);
x86_cpu_to_apicid[cpu] = apicid;
- /*
- * We remove it from the pidhash and the runqueue
- * once we got the process:
- */
- init_idle(idle,cpu);
-
- unhash_process(idle);
-
cpu_pda[cpu].pcurrent = idle;
start_rip = setup_trampoline();
init_rsp = idle->thread.rsp;
- init_tss[cpu].rsp0 = init_rsp;
+ per_cpu(init_tss,cpu).rsp0 = init_rsp;
initial_code = start_secondary;
clear_ti_thread_flag(idle->thread_info, TIF_FORK);
Dprintk("CPU has booted.\n");
} else {
boot_error = 1;
- if (*((volatile unsigned char *)phys_to_virt(8192))
+ if (*((volatile unsigned char *)phys_to_virt(SMP_TRAMPOLINE_BASE))
== 0xA5)
/* trampoline started but...? */
printk("Stuck ??\n");
cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
cpucount--;
+ x86_cpu_to_apicid[cpu] = BAD_APICID;
+ x86_cpu_to_log_apicid[cpu] = BAD_APICID;
}
-
- /* mark "stuck" area as not stuck */
- *((volatile unsigned *)phys_to_virt(8192)) = 0;
}
cycles_t cacheflush_time;
if (apicid == boot_cpu_id || (apicid == BAD_APICID))
continue;
- if (!cpu_isset(apicid, phys_cpu_present_map))
+ if (!physid_isset(apicid, phys_cpu_present_map))
continue;
if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
continue;
}
/*
- * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so
- * that we can tell the sibling CPU efficiently.
+ * Construct cpu_sibling_map[], so that we can tell the
+ * sibling CPU efficiently.
*/
- if (cpu_has_ht && smp_num_siblings > 1) {
- for (cpu = 0; cpu < NR_CPUS; cpu++)
- cpu_sibling_map[cpu] = NO_PROC_ID;
-
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- int i;
- if (!cpu_isset(cpu, cpu_callout_map))
- continue;
+ for (cpu = 0; cpu < NR_CPUS; cpu++)
+ cpus_clear(cpu_sibling_map[cpu]);
+
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ int siblings = 0;
+ int i;
+ if (!cpu_isset(cpu, cpu_callout_map))
+ continue;
+ if (smp_num_siblings > 1) {
for (i = 0; i < NR_CPUS; i++) {
- if (i == cpu || !cpu_isset(i, cpu_callout_map))
+ if (!cpu_isset(i, cpu_callout_map))
continue;
if (phys_proc_id[cpu] == phys_proc_id[i]) {
- cpu_sibling_map[cpu] = i;
- break;
+ siblings++;
+ cpu_set(i, cpu_sibling_map[cpu]);
}
}
- if (cpu_sibling_map[cpu] == (char)NO_PROC_ID) {
- smp_num_siblings = 1;
- printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu);
- }
+ } else {
+ siblings++;
+ cpu_set(cpu, cpu_sibling_map[cpu]);
}
+
+ if (siblings != smp_num_siblings) {
+ printk(KERN_WARNING
+ "WARNING: %d siblings found for CPU%d, should be %d\n",
+ siblings, cpu, smp_num_siblings);
+ smp_num_siblings = siblings;
+ }
}
Dprintk("Boot done.\n");
void __init smp_cpus_done(unsigned int max_cpus)
{
+#ifdef CONFIG_X86_IO_APIC
+ setup_ioapic_dest();
+#endif
zap_low_mappings();
}