#include <cpu/cpu.h>
#if CONFIG_SMP == 1
-
-#if CONFIG_RAMBASE >= 0x100000
/* This is a lot more paranoid now, since Linux can NOT handle
* being told there is a CPU when none exists. So any errors
* will return 0, meaning no CPU.
{
return (unsigned long)orig_start_eip & 0xffff; // 16 bit to avoid 0xa0000
}
-#endif
#if CONFIG_HAVE_ACPI_RESUME == 1
char *lowmem_backup;
static void copy_secondary_start_to_1m_below(void)
{
-#if CONFIG_RAMBASE >= 0x100000
extern char _secondary_start_end[];
unsigned long code_size;
unsigned long start_eip;
memcpy((unsigned char *)start_eip, (unsigned char *)_secondary_start, code_size);
printk(BIOS_DEBUG, "start_eip=0x%08lx, offset=0x%08lx, code_size=0x%08lx\n", start_eip, ((unsigned long)_secondary_start - start_eip), code_size);
-#endif
}
static int lapic_start_cpu(unsigned long apicid)
return 0;
}
-#if CONFIG_RAMBASE >= 0x100000
start_eip = get_valid_start_eip((unsigned long)_secondary_start);
-#else
- start_eip = (unsigned long)_secondary_start;
-#endif
#if !defined (CONFIG_CPU_AMD_MODEL_10XXX) && !defined (CONFIG_CPU_AMD_MODEL_14XXX)
num_starts = 2;
if (result) {
result = 0;
- /* Wait 1s or until the new the new cpu calls in */
+ /* Wait 1s or until the new cpu calls in */
for(count = 0; count < 100000 ; count++) {
if (secondary_stack == 0) {
result = 1;
}
#if CONFIG_AP_IN_SIPI_WAIT == 1
+
+/**
+ * Sending INIT IPI to self is equivalent of asserting #INIT with a bit of delay.
+ * An undefined number of instruction cycles will complete. All global locks
+ * must be released before INIT IPI and no printk is allowed after this.
+ * De-asserting INIT IPI is a no-op on later Intel CPUs.
+ *
+ * If you set DEBUG_HALT_SELF to 1, printk's after INIT IPI are enabled
+ * but running thread may halt without releasing the lock and effectively
+ * deadlock other CPUs.
+ */
+#define DEBUG_HALT_SELF 0
+
/**
* Normally this function is defined in lapic.h as an always inline function
* that just keeps the CPU in a hlt() loop. This does not work on all CPUs.
lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT);
/* wait for the ipi send to finish */
-#if 0
- // When these two printk(BIOS_SPEW, ...) calls are not removed, the
- // machine will hang when log level is SPEW. Why?
+#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Waiting for send to finish...\n");
#endif
timeout = 0;
do {
-#if 0
+#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "+");
#endif
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
+#if DEBUG_HALT_SELF
printk(BIOS_ERR, "timed out\n");
+#endif
}
mdelay(10);
+#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Deasserting INIT.\n");
+#endif
/* Deassert the LAPIC INIT */
lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(id));
lapic_write_around(LAPIC_ICR, LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT);
+#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "Waiting for send to finish...\n");
+#endif
timeout = 0;
do {
+#if DEBUG_HALT_SELF
printk(BIOS_SPEW, "+");
+#endif
udelay(100);
send_status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
+#if DEBUG_HALT_SELF
printk(BIOS_ERR, "timed out\n");
+#endif
}
while(1) {
}
#endif
+#ifdef __SSE3__
+static __inline__ __attribute__((always_inline)) unsigned long readcr4(void)
+{
+ unsigned long value;
+ __asm__ __volatile__ (
+ "mov %%cr4, %[value]"
+ : [value] "=a" (value));
+ return value;
+}
+
+static __inline__ __attribute__((always_inline)) void writecr4(unsigned long Data)
+{
+ __asm__ __volatile__ (
+ "mov %%eax, %%cr4"
+ :
+ : "a" (Data)
+ );
+}
+#endif
+
/* C entry point of secondary cpus */
void secondary_cpu_init(void)
{
atomic_inc(&active_cpus);
#if CONFIG_SERIAL_CPU_INIT == 1
- #if CONFIG_MAX_CPUS>2
spin_lock(&start_cpu_lock);
- #endif
+#endif
+
+#ifdef __SSE3__
+ /*
+ * Seems that CR4 was cleared when AP start via lapic_start_cpu()
+ * Turn on CR4.OSFXSR and CR4.OSXMMEXCPT when SSE options enabled
+ */
+ u32 cr4_val;
+ cr4_val = readcr4();
+ cr4_val |= (1 << 9 | 1 << 10);
+ writecr4(cr4_val);
#endif
cpu_initialize();
#if CONFIG_SERIAL_CPU_INIT == 1
- #if CONFIG_MAX_CPUS>2
spin_unlock(&start_cpu_lock);
- #endif
#endif
atomic_dec(&active_cpus);
cpu->path.apic.apic_id);
}
#if CONFIG_SERIAL_CPU_INIT == 1
- #if CONFIG_MAX_CPUS>2
udelay(10);
- #endif
#endif
}