diff options
author | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:54:17 +0000 |
---|---|---|
committer | Eric Biederman <ebiederm@xmission.com> | 2004-10-14 20:54:17 +0000 |
commit | b78c1972feed4c57eebba8f94de86a91e32c3fa7 (patch) | |
tree | 2ba60cfe9866f4d1e2de1d9727d0e548139afb35 /src/arch/i386/smp | |
parent | cadfd4c462673bcb44cdb1f193e52c95a888762a (diff) |
- First pass through with with device tree enhancement merge. Most of the mechanisms should
be in place but don't expect anything to quite work yet.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1662 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386/smp')
-rw-r--r-- | src/arch/i386/smp/Config.lb | 6 | ||||
-rw-r--r-- | src/arch/i386/smp/mpspec.c | 44 | ||||
-rw-r--r-- | src/arch/i386/smp/secondary.S | 76 | ||||
-rw-r--r-- | src/arch/i386/smp/start_stop.c | 240 |
4 files changed, 24 insertions, 342 deletions
diff --git a/src/arch/i386/smp/Config.lb b/src/arch/i386/smp/Config.lb index d1e365c073..b41f5c295e 100644 --- a/src/arch/i386/smp/Config.lb +++ b/src/arch/i386/smp/Config.lb @@ -1,12 +1,8 @@ uses HAVE_MP_TABLE -uses CONFIG_SMP if HAVE_MP_TABLE object mpspec.o end #object ioapic.o CONFIG_IOAPIC -if CONFIG_SMP - object start_stop.o - object secondary.S -end + diff --git a/src/arch/i386/smp/mpspec.c b/src/arch/i386/smp/mpspec.c index 4a1e233be9..babfcbdca2 100644 --- a/src/arch/i386/smp/mpspec.c +++ b/src/arch/i386/smp/mpspec.c @@ -1,10 +1,9 @@ #include <console/console.h> #include <cpu/cpu.h> -#include <smp/start_stop.h> #include <arch/smp/mpspec.h> #include <string.h> -#include <cpu/p5/cpuid.h> -#include <cpu/p6/apic.h> +#include <arch/cpu.h> +#include <cpu/x86/lapic.h> unsigned char smp_compute_checksum(void *v, int len) { @@ -94,30 +93,33 @@ void smp_write_processor(struct mp_config_table *mc, * Having the proper apicid's in the table so the non-bootstrap * processors can be woken up should be enough. */ -void smp_write_processors(struct mp_config_table *mc, - unsigned long *processor_map) +void smp_write_processors(struct mp_config_table *mc) { - int i; - int processor_id; + int boot_apic_id; unsigned apic_version; unsigned cpu_features; unsigned cpu_feature_flags; - int eax, ebx, ecx, edx; - processor_id = this_processors_id(); - apic_version = apic_read(APIC_LVR) & 0xff; - cpuid(1, &eax, &ebx, &ecx, &edx); - cpu_features = eax; - cpu_feature_flags = edx; - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - unsigned long cpu_apicid = initial_apicid[i]; + struct cpuid_result result; + device_t cpu; + boot_apic_id = lapicid(); + apic_version = lapic_read(LAPIC_LVR) & 0xff; + result = cpuid(1); + cpu_features = result.eax; + cpu_feature_flags = result.edx; + for(cpu = dev_root.link[1].children; cpu; cpu = cpu->sibling) { unsigned long cpu_flag; - if(initial_apicid[i]==-1) + if (cpu->path.type != DEVICE_PATH_APIC) { + continue; + } + if (!cpu->enabled) { continue; + } cpu_flag = MPC_CPU_ENABLED; - if (processor_map[i] & CPU_BOOTPROCESSOR) { - cpu_flag |= MPC_CPU_BOOTPROCESSOR; + if (boot_apic_id == cpu->path.u.apic.apic_id) { + cpu_flag = MPC_CPU_ENABLED; } - smp_write_processor(mc, cpu_apicid, apic_version, + smp_write_processor(mc, + cpu->path.u.apic.apic_id, apic_version, cpu_flag, cpu_features, cpu_feature_flags ); } @@ -136,8 +138,8 @@ void smp_write_bus(struct mp_config_table *mc, } void smp_write_ioapic(struct mp_config_table *mc, - unsigned char id, unsigned char ver, - unsigned long apicaddr) + unsigned char id, unsigned char ver, + unsigned long apicaddr) { struct mpc_config_ioapic *mpc; mpc = smp_next_mpc_entry(mc); diff --git a/src/arch/i386/smp/secondary.S b/src/arch/i386/smp/secondary.S deleted file mode 100644 index c27d6282b0..0000000000 --- a/src/arch/i386/smp/secondary.S +++ /dev/null @@ -1,76 +0,0 @@ -#include <arch/asm.h> -#include <arch/intel.h> -#include <cpu/p6/mtrr.h> -#include <cpu/p6/apic.h> - .text - .globl _secondary_start - .balign 4096 -_secondary_start: - .code16 - cli - xorl %eax, %eax - movl %eax, %cr3 /* Invalidate TLB*/ - - /* On hyper threaded cpus invalidating the cache here is - * very very bad. Don't. - */ - - /* setup the data segment */ - movw %cs, %ax - movw %ax, %ds - - data32 lgdt gdtaddr - _secondary_start - - movl %cr0, %eax - andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ - orl $0x60000001, %eax /* CD, NW, PE = 1 */ - movl %eax, %cr0 - - ljmpl $0x10, $1f -1: - .code32 - movw $0x18, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movw %ax, %fs - movw %ax, %gs - - /* Enable the local apic, and map it where we expext it */ - movl $APIC_BASE_MSR, %ecx - rdmsr - orl $APIC_BASE_MSR_ENABLE, %eax - andl $(~APIC_BASE_MSR_ADDR_MASK), %eax - orl $APIC_DEFAULT_BASE, %eax - wrmsr - - /* Get the apic_id */ - movl (APIC_ID + APIC_DEFAULT_BASE), %edi - shrl $24, %edi - - /* Get the cpu index (CONFIG_MAX_CPUS on error) */ - movl $-4, %ebx -1: addl $4, %ebx - cmpl $(CONFIG_MAX_CPUS << 2), %ebx - je 2 - cmpl %edi, initial_apicid(%ebx) - jne 1b -2: shrl $2, %ebx - - /* set the stack pointer */ - movl $_estack, %esp - movl %ebx, %eax - movl $STACK_SIZE, %ebx - mull %ebx - subl %eax, %esp - - call secondary_cpu_init -1: hlt - jmp 1b - -gdtaddr: - .word gdt_limit /* the table limit */ - .long gdt /* we know the offset */ - - -.code32 diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c deleted file mode 100644 index bf26437984..0000000000 --- a/src/arch/i386/smp/start_stop.c +++ /dev/null @@ -1,240 +0,0 @@ -#include <smp/start_stop.h> -#include <arch/smp/mpspec.h> -#include <cpu/p6/apic.h> -#include <delay.h> -#include <string.h> -#include <console/console.h> -#include <arch/smp/lapic.h> -#include <arch/hlt.h> - - -unsigned long this_processors_id(void) -{ - return lapicid(); -} - -int processor_index(unsigned long apicid) -{ - int i; - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - if (initial_apicid[i] == apicid) { - return i; - } - } - return -1; -} - -void stop_cpu(unsigned long apicid) -{ - int timeout; - unsigned long send_status; - - /* send an APIC INIT to myself */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT); - - /* wait for the ipi send to finish */ - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("timed out\n"); - } - mdelay(10); - - printk_spew("Deasserting INIT.\n"); - /* Deassert the APIC INIT */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("timed out\n"); - } - - while(1) { - hlt(); - } -} - -/* 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. - * - * We actually handling that case by noting which cpus startup - * and not telling anyone about the ones that dont. - */ -int start_cpu(unsigned long apicid) -{ - int timeout; - unsigned long send_status, accept_status, start_eip; - int j, num_starts, maxlvt; - extern char _secondary_start[]; - - /* - * Starting actual IPI sequence... - */ - - printk_spew("Asserting INIT.\n"); - - /* - * Turn INIT on target chip - */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* - * Send IPI - */ - - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT - | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("CPU %d: First apic write timed out. Disabling\n", - apicid); - // too bad. - printk_err("ESR is 0x%x\n", apic_read(APIC_ESR)); - if (apic_read(APIC_ESR)) { - printk_err("Try to reset ESR\n"); - apic_write_around(APIC_ESR, 0); - printk_err("ESR is 0x%x\n", apic_read(APIC_ESR)); - } - return 0; - } - mdelay(10); - - printk_spew("Deasserting INIT.\n"); - - /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* Send IPI */ - apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - if (timeout >= 1000) { - printk_err("CPU %d: Second apic write timed out. Disabling\n", - apicid); - // too bad. - return 0; - } - - start_eip = (unsigned long)_secondary_start; - printk_spew("start_eip=0x%08lx\n", start_eip); - - num_starts = 2; - - /* - * Run STARTUP IPI loop. - */ - printk_spew("#startup loops: %d.\n", num_starts); - - maxlvt = 4; - - for (j = 1; j <= num_starts; j++) { - printk_spew("Sending STARTUP #%d to %u.\n", j, apicid); - apic_read_around(APIC_SPIV); - apic_write(APIC_ESR, 0); - apic_read(APIC_ESR); - printk_spew("After apic_write.\n"); - - /* - * STARTUP IPI - */ - - /* Target chip */ - apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid)); - - /* Boot on the stack */ - /* Kick the second */ - apic_write_around(APIC_ICR, APIC_DM_STARTUP - | (start_eip >> 12)); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(300); - - printk_spew("Startup point 1.\n"); - - printk_spew("Waiting for send to finish...\n"); - timeout = 0; - do { - printk_spew("+"); - udelay(100); - send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY; - } while (send_status && (timeout++ < 1000)); - - /* - * Give the other CPU some time to accept the IPI. - */ - udelay(200); - /* - * Due to the Pentium erratum 3AP. - */ - if (maxlvt > 3) { - apic_read_around(APIC_SPIV); - apic_write(APIC_ESR, 0); - } - accept_status = (apic_read(APIC_ESR) & 0xEF); - if (send_status || accept_status) - break; - } - printk_spew("After Startup.\n"); - if (send_status) - printk_warning("APIC never delivered???\n"); - if (accept_status) - printk_warning("APIC delivery error (%lx).\n", accept_status); - if (send_status || accept_status) - return 0; - return 1; -} - - -void startup_other_cpus(unsigned long *processor_map) -{ - unsigned long apicid = this_processors_id(); - int i; - - /* Assume the cpus are densly packed by apicid */ - for(i = 0; i < CONFIG_MAX_CPUS; i++) { - unsigned long cpu_apicid = initial_apicid[i]; - if (cpu_apicid == -1) { - printk_err("CPU %d not found\n",i); - processor_map[i] = 0; - continue; - } - if (cpu_apicid == apicid ) { - continue; - } - if (!start_cpu(cpu_apicid)) { - /* Put an error in processor_map[i]? */ - printk_err("CPU %d/%u would not start!\n", - i, cpu_apicid); - processor_map[i] = 0; - } - } -} |