diff options
author | Ronald G. Minnich <rminnich@gmail.com> | 2009-03-11 16:17:37 +0000 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2009-03-11 16:17:37 +0000 |
commit | 5a90884bd46b8b88bba14476c6ca37e968760848 (patch) | |
tree | abeb0846e5acc3d98ff699b4606d010967c164ac | |
parent | 1ef9d2f412e6e18bec9a268d9bacf8d4d6374158 (diff) | |
download | coreboot-5a90884bd46b8b88bba14476c6ca37e968760848.tar.gz coreboot-5a90884bd46b8b88bba14476c6ca37e968760848.tar.bz2 coreboot-5a90884bd46b8b88bba14476c6ca37e968760848.zip |
last kontron commit.
This is a potentially good pointer to where someone can take this.
While startup was working, BSP now explodes once the AP stops, while
BSP is doing startup IPI loop send #2. The code needs to be hardened; I
think use of the shared variables would really make it much more solid.
This would be a good undergrad student project if someone is looking for one.
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
Acked-by: Stefan Reinauer <stepan@coresystems.de>
git-svn-id: svn://coreboot.org/repository/coreboot-v3@1145 f3766cd6-281f-0410-b1cd-43a5c92072e9
-rw-r--r-- | arch/x86/intel/core2/init_cpus.c | 180 | ||||
-rw-r--r-- | arch/x86/secondary.S | 62 | ||||
-rw-r--r-- | device/pci_device.c | 3 | ||||
-rw-r--r-- | device/pci_rom.c | 2 | ||||
-rw-r--r-- | include/lib.h | 6 | ||||
-rw-r--r-- | lib/stage2.c | 39 | ||||
-rw-r--r-- | mainboard/kontron/986lcd-m/Makefile | 11 | ||||
-rw-r--r-- | mainboard/kontron/986lcd-m/dts | 5 | ||||
-rw-r--r-- | mainboard/kontron/986lcd-m/initram.c | 3 |
9 files changed, 258 insertions, 53 deletions
diff --git a/arch/x86/intel/core2/init_cpus.c b/arch/x86/intel/core2/init_cpus.c index 89ddd4282f55..b9c8612ba53d 100644 --- a/arch/x86/intel/core2/init_cpus.c +++ b/arch/x86/intel/core2/init_cpus.c @@ -21,7 +21,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <mainboard.h> #include <types.h> #include <lib.h> #include <console.h> @@ -73,6 +72,7 @@ unsigned int get_nodes(void) int nodes, siblings; result = cpuid(1); /* See how many sibling cpus we have */ + printk(BIOS_DEBUG, "cpuid(1) ebx is %08x\n", result.ebx); siblings = (result.ebx >> 16) & 0xff; if (siblings < 1) { siblings = 1; @@ -204,6 +204,9 @@ static int lapic_start_cpu(unsigned long apicid, u32 *secondary_base) * Starting actual IPI sequence... */ + printk(BIOS_SPEW, "Before Startup.apicid %ld\n", apicid); + printk(BIOS_SPEW, "Before Startup.sb[0] %p @0 %08x\n", + (void *) secondary_base[0], *(u32 *) 0); printk(BIOS_SPEW, "Asserting INIT.\n"); /* @@ -321,7 +324,11 @@ static int lapic_start_cpu(unsigned long apicid, u32 *secondary_base) if (send_status || accept_status) break; } + printk(BIOS_SPEW, "udelay(1000000)\n"); + udelay(1000000); printk(BIOS_SPEW, "After Startup.sb[-1] %p\n", (void *) secondary_base[-1]); + printk(BIOS_SPEW, "After Startup.sb[0] %p @0 %08x\n", + (void *) secondary_base[0], *(u32 *) 0); if (send_status) printk(BIOS_WARNING, "APIC never delivered???\n"); if (accept_status) @@ -335,13 +342,13 @@ static int lapic_start_cpu(unsigned long apicid, u32 *secondary_base) /* we compile the secondary start code such that this looks like a stack frame */ struct stack { - u32 post; - u32 index; - u32 apicid; - struct atomic *active_cpus; + u32 data[16384/sizeof(u32) - 7]; struct spinlock *start_cpu_lock; + struct atomic *active_cpus; + u32 apicid; + u32 index; + u32 post; u32 callerpc; - u32 data[16384/sizeof(u32) - 7]; }; struct stackmem { @@ -377,18 +384,25 @@ int start_cpu(u32 apicid, struct atomic *active_cpus, struct spinlock *start_cpu stackmem->stacks[index].post = 0; stackmem->stacks[index].active_cpus = active_cpus; stackmem->stacks[index].start_cpu_lock = start_cpu_lock; + printk(BIOS_SPEW, "stack[index, apicid, post, active_cpus, start_cpu_lock] = [%lx, %x, %d, %p, %p]\n", index, apicid, 0, active_cpus, start_cpu_lock); /* Advertise the new stack to start_cpu */ printk(BIOS_SPEW, "Set stack @ %p to %p\n", &secondary_base[-1], (void *)stack_end); secondary_base[-1] = stack_end; /* Start the cpu */ result = lapic_start_cpu(apicid, secondary_base); + printk(BIOS_SPEW, "we think we started it. The stack value is 0x%p (should be 0)\n", (void *)secondary_base[-1]); if (result) { + printk(BIOS_SPEW, "Spinning on post which is now 0x%x\n", + stackmem->stacks[index].post); result = 0; /* Wait 1s or until the new the new cpu calls in */ - for(count = 0; count < 100000 ; count++) { - if (stackmem->stacks[index].post) { + for(count = 0; count < 1000000 ; count++) { + printk(BIOS_SPEW, + "BSP post 0x%x\n", + stackmem->stacks[index].post); + if (stackmem->stacks[index].post >= AP_STOP_OK) { result = 1; break; } @@ -476,9 +490,13 @@ void __attribute__((regparm(0))) secondary_cpu_init( struct atomic *active_cpus, struct spinlock *start_cpu_lock) { +//printk(BIOS_SPEW, "secondary start\n"); +//printk(BIOS_SPEW, "[post, index, apicid,active_cpus, start_cpu_lock] = [%x, %x, %d, %p, %p]\n", post, index, apicid, active_cpus, start_cpu_lock); post = AP_START; +//printk(BIOS_SPEW, "secondary post %d\n", post); atomic_inc(active_cpus); post = AP_ACTIVEUP; +//printk(BIOS_SPEW, "secondary post %d\n", post); if (SERIAL_CPU_INIT && (CONFIG_MAX_PHYSICAL_CPUS > 2)) spin_lock(start_cpu_lock); post = AP_LOCKED; @@ -531,6 +549,104 @@ static void wait_other_cpus_stop(struct atomic *active_cpus) printk(BIOS_DEBUG, "All AP CPUs stopped\n"); } +/* this should be a library call. */ +static void fill_processor_name(char *processor_name, int len) +{ + struct cpuid_result regs; + char temp_processor_name[49]; + char *processor_name_start; + unsigned int *name_as_ints = (unsigned int *)temp_processor_name; + int i; + + if (len > sizeof(temp_processor_name)) + len = sizeof(temp_processor_name); + + for (i=0; i<3; i++) { + regs = cpuid(0x80000002 + i); + name_as_ints[i*4 + 0] = regs.eax; + name_as_ints[i*4 + 1] = regs.ebx; + name_as_ints[i*4 + 2] = regs.ecx; + name_as_ints[i*4 + 3] = regs.edx; + } + + temp_processor_name[48] = 0; + + /* Skip leading spaces */ + processor_name_start = temp_processor_name; + while (*processor_name_start == ' ') + processor_name_start++; + + memset(processor_name, 0, 49); + memcpy(processor_name, processor_name_start, len); +} + +#define IA32_FEATURE_CONTROL 0x003a + +#define CPUID_VMX (1 << 5) +#define CPUID_SMX (1 << 6) +static void enable_vmx(void) +{ + struct cpuid_result regs; + struct msr msr; + + msr = rdmsr(IA32_FEATURE_CONTROL); + + if (msr.lo & (1 << 0)) { + /* VMX locked. If we set it again we get an illegal + * instruction + */ + return; + } + + regs = cpuid(1); + if (regs.ecx & CPUID_VMX) { + msr.lo |= (1 << 2); + if (regs.ecx & CPUID_SMX) + msr.lo |= (1 << 1); + } + + wrmsr(IA32_FEATURE_CONTROL, msr); + + msr.lo |= (1 << 0); /* Set lock bit */ + + wrmsr(IA32_FEATURE_CONTROL, msr); +} + +#define PMG_CST_CONFIG_CONTROL 0xe2 +static void configure_c_states(void) +{ + struct msr msr; + + msr = rdmsr(PMG_CST_CONFIG_CONTROL); + msr.lo &= ~(1 << 9); // Issue a single stop grant cycle upon stpclk + + // TODO Do we want Deep C4 and Dynamic L2 shrinking? + wrmsr(PMG_CST_CONFIG_CONTROL, msr); +} + +#define IA32_MISC_ENABLE 0x1a0 +static void configure_misc(void) +{ + struct msr msr; + + msr = rdmsr(IA32_MISC_ENABLE); + msr.lo |= (1 << 3); /* TM1 enable */ + msr.lo |= (1 << 13); /* TM2 enable */ + msr.lo |= (1 << 17); /* Bidirectional PROCHOT# */ + + msr.lo |= (1 << 10); /* FERR# multiplexing */ + + // TODO: Only if IA32_PLATFORM_ID[17] = 0 and IA32_PLATFORM_ID[50] = 1 + msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */ + + // TODO Do we want Deep C4 and Dynamic L2 shrinking? + wrmsr(IA32_MISC_ENABLE, msr); + + msr.lo |= (1 << 20); /* Lock Enhanced SpeedStep Enable */ + wrmsr(IA32_MISC_ENABLE, msr); +} + + /** * Init all the CPUs. * this was unnecessarily tricky in v2 (surprise!) @@ -559,12 +675,13 @@ static void wait_other_cpus_stop(struct atomic *active_cpus) * @param sysinfo The sys_info pointer * @returns the BSP APIC ID */ -unsigned int init_cpus(unsigned cpu_init_detectedx, +unsigned int cpu_phase1(unsigned cpu_init_detectedx, struct sys_info *sysinfo) { /* Number of cpus that are currently running in coreboot */ struct atomic active_cpus; u32 *secondary_base; + char processor_name[49]; /* every AP gets a stack. The stacks are linear and start at 0x100000 */ struct spinlock start_cpu_lock; @@ -579,10 +696,55 @@ unsigned int init_cpus(unsigned cpu_init_detectedx, // why here? In case some day we can start core1 in amd_sibling_init secondary_base = copy_secondary_start_to_1m_below(); + /* Turn on caching if we haven't already */ + enable_cache(); + + /* Update the microcode * + intel_update_microcode(microcode_updates); + * needs to be rewritten to use LAR, not code include hacks + */ + + /* Print processor name */ + fill_processor_name(processor_name, sizeof(processor_name)); + printk(BIOS_INFO, "CPU: %s.\n", processor_name); + +#ifdef CONFIG_USBDEBUG_DIRECT + // Is this caution really needed? + if(!ehci_debug_addr) + ehci_debug_addr = get_ehci_debug(); + set_ehci_debug(0); +#endif + + /* Setup MTRRs */ + x86_setup_mtrrs(36); + x86_mtrr_check(); + +#ifdef CONFIG_USBDEBUG_DIRECT + set_ehci_debug(ehci_debug_addr); +#endif + + /* Enable the local cpu apics */ + /* do we need this in v3? not sure + setup_lapic(); + */ + + /* Enable virtualization */ + enable_vmx(); + + /* Configure C States */ + configure_c_states(); + + /* Configure Enhanced SpeedStep and Thermal Sensors */ + configure_misc(); + + /* TODO: PIC thermal sensor control */ + + #ifdef CONFIG_SMM smm_init(); #endif + /* Start up my cpu siblings */ if (! SERIAL_CPU_INIT) /* start all aps at first, so we can init ECC all together */ start_other_cpus(get_nodes(), &active_cpus, &start_cpu_lock, &last_cpu_index, secondary_base); diff --git a/arch/x86/secondary.S b/arch/x86/secondary.S index 4fa6f4e17027..62bcbccab58c 100644 --- a/arch/x86/secondary.S +++ b/arch/x86/secondary.S @@ -21,6 +21,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ + +/* POST_ZERO writes a POST_CODE at zero. Note that once we load %ds from %cs, "0" is at the start of this function! + * This is debug only; you can't use it on systems with more than one core. It should be left off by default. + */ +#define NO_POST_ZERO + +#ifdef NO_POST_ZERO +#define POST_ZERO(x) +#else +#define POST_ZERO(x) movw x, 0 +#endif .text .globl _secondary_start, _secondary_start_end _secondary_start: @@ -28,58 +39,57 @@ _secondary_start: .code16 .balign 4096 cli - movw $0xdead, 0 - movw $0xbeef, 2 + POST_ZERO($0xdead) xorl %eax, %eax movl %eax, %cr3 /* Invalidate TLB*/ /* On hyper threaded cpus, invalidating the cache here is * very very bad. Don't. */ - movw $0, 0 + POST_ZERO($0) movl $1b, %ebx - movw $1, 0 - movw $2, 0 + POST_ZERO($1) + POST_ZERO($2) /* setup the data segment */ movw %cs, %ax movw %ax, 2 - movw $3, 0 + POST_ZERO($3) movw %ax, %ds - movw $4, 0 + POST_ZERO($4) /* past this point, "0" means ds:0, i.e. cs:0, or the * segment part of the address. */ data32 lgdt gdtaddr - _secondary_start // data32 lgdt %cs:gdtptr - movw $5, 0 + POST_ZERO($5) movl %cr0, %eax - movw $6, 0 + POST_ZERO($6) andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ - movw $7, 0 + POST_ZERO($7) orl $0x60000001, %eax /* CD, NW, PE = 1 */ - movw $8, 0 + POST_ZERO($8) movl %eax, %cr0 - movw $9, 0 - hlt - /* tested to this point but not past it */ + POST_ZERO($9) - /* I am pretty sure this just jumps back into - * ROM; it's an abs jump - */ - data32 ljmp $0x10, $secondary32 - movw $0xa, 0 + /* This jump pops us into 32-bit protected mode */ + data32 ljmp $0x8, $secondary32 + POST_ZERO($0xa) 1: .code32 secondary32: - hlt - movw $0x18, %ax + POST_ZERO($0x11) + movw $0x10, %ax movw %ax, %ds + /* having a post here for testing is useful. + *If ds is bad for some reason, we'll reboot */ + POST_ZERO($0x13) movw %ax, %es movw %ax, %ss movw %ax, %fs movw %ax, %gs + POST_ZERO($0x17) /* Load the Interrupt descriptor table */ lidt idtarg @@ -87,6 +97,8 @@ secondary32: /* Set the stack pointer */ movl -4(%ebx),%esp movl $0, -4(%ebx) + /* tested to this point but not past it */ + /* AP sees the stack value set to 0 */ call secondary_cpu_init 1: hlt @@ -108,14 +120,6 @@ gdtptr: /* selgdt 0x10, flat data segment */ .word 0xffff, 0x0000 .byte 0x00, 0x93, 0xcf, 0x00 - - /* selgdt 0x18, flat code segment for CAR */ - .word 0xffff, 0x0000 - .byte 0x00, 0x9b, 0xcf, 0x00 - - /* selgdt 0x20, flat data segment for CAR */ - .word 0xffff, 0x0000 - .byte 0x00, 0x93, 0xcf, 0x00 gdt_end: diff --git a/device/pci_device.c b/device/pci_device.c index c76092dfddb2..c5cee3c540e9 100644 --- a/device/pci_device.c +++ b/device/pci_device.c @@ -1304,7 +1304,8 @@ unsigned int do_pci_scan_bridge(struct device *dev, unsigned int max, pci_write_config32(dev, PCI_PRIMARY_BUS, buses); pci_write_config16(dev, PCI_COMMAND, cr); - printk(BIOS_DEBUG, "%s DONE\n", __func__); + printk(BIOS_DEBUG, "%s DONE: [%x, %x, %x]\n", __func__, + dev->bus->secondary, bus->secondary, bus->subordinate); printk(BIOS_SPEW, "%s returns max %d\n", __func__, max); return max; } diff --git a/device/pci_rom.c b/device/pci_rom.c index 48dd1e0635ff..ed7c8862e36e 100644 --- a/device/pci_rom.c +++ b/device/pci_rom.c @@ -47,7 +47,7 @@ struct rom_header *pci_rom_probe(struct device *dev) init_archive(&archive); sprintf(pcifile, "pci%04x,%04x.rom", dev->id.pci.vendor, dev->id.pci.device); - + printk(BIOS_DEBUG, "pci_rom_probe: search for %s\n", pcifile); ret = find_file(&archive, pcifile, &result); if (ret) { printk(BIOS_INFO, "No option rom for onboard device.\n"); diff --git a/include/lib.h b/include/lib.h index 2132b2f413ed..0af0e2a7580a 100644 --- a/include/lib.h +++ b/include/lib.h @@ -52,4 +52,10 @@ void beep_long(void); /* Optional ramtest. */ int ram_check(unsigned long start, unsigned long stop); +/* required: a way to tell if this is a: + * power-on/reset (coldboot) OR + * coreboot has initiated a reset (warmboot). + */ +int is_coldboot(void); + #endif /* LIB_H */ diff --git a/lib/stage2.c b/lib/stage2.c index edd09f496403..899fb734e654 100644 --- a/lib/stage2.c +++ b/lib/stage2.c @@ -27,6 +27,38 @@ #include <console.h> #include <device/device.h> #include <tables.h> +#include <globalvars.h> +#include <lib.h> + +/** + * CPU init code which runs BEFORE any stage2 dev_phase1 is run. + * This code might, for example, init ECC on all cores. + * + * @param coldboot Is this a power-on coldboot + * @param sysinfo sysinfo pointer + * @returns 0 on success; error number otherwise + */ +unsigned int __attribute__((weak)) cpu_phase1(unsigned int coldboot, + struct sys_info *sysinfo) +{ + printk(BIOS_SPEW, "cpu_phase1: %s: nothing to do.\n", coldboot? "Coldboot" : "Warmboot"); + return 0; +} + +/** + * CPU init code which runs AFTER ALL stage2 dev_phases are run. + * This code might, for example, install an SMI handler + * + * @param coldboot Is this a power-on coldboot + * @param sysinfo sysinfo pointer + * @returns 0 on success; error number otherwise + */ +unsigned int __attribute__((weak)) cpu_phase2(unsigned int coldboot, + struct sys_info *sysinfo) +{ + printk(BIOS_SPEW, "cpu_phase2: %s: nothing to do.\n", coldboot? "Coldboot" : "Warmboot"); + return 0; +} /** * Main function of the DRAM part of coreboot. @@ -44,8 +76,11 @@ void *stage2(void) { void *mbi; - + struct sys_info *sysinfo; + struct global_vars *global_vars(void); post_code(POST_STAGE2_BEGIN); + sysinfo = &(global_vars()->sys_info); + cpu_phase1(is_coldboot(), sysinfo); dev_init(); /* Phase 1 was console init and making printk work. Both functions are @@ -85,6 +120,8 @@ void *stage2(void) dev_phase6(); show_all_devs(BIOS_DEBUG, "After phase 6."); + cpu_phase2(is_coldboot(), sysinfo); + /* Write tables to pass information to the payloads. */ post_code(POST_STAGE2_WRITE_TABLES); mbi = write_tables(); diff --git a/mainboard/kontron/986lcd-m/Makefile b/mainboard/kontron/986lcd-m/Makefile index c7419ddfcea4..39474e4596aa 100644 --- a/mainboard/kontron/986lcd-m/Makefile +++ b/mainboard/kontron/986lcd-m/Makefile @@ -23,17 +23,16 @@ STAGE0_MAINBOARD_SRC := $(src)/lib/clog2.c \ $(src)/mainboard/$(MAINBOARDDIR)/stage1.c \ $(src)/mainboard/$(MAINBOARDDIR)/stage1_debug.c \ + $(src)/northbridge/intel/i945//reset_test.c \ INITRAM_SRC= $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ - $(src)/northbridge/intel/i945//reset_test.c \ - $(src)/arch/x86/intel/core2/init_cpus.c \ INITRAM_OBJ = \ - $(obj)/arch/x86/secondary.o \ -STAGE2_CHIPSET_SRC= - -STAGE2_MAINBOARD_SRC = +STAGE2_CHIPSET_SRC= \ + $(src)/northbridge/intel/i945//reset_test.c \ + $(src)/arch/x86/intel/core2/init_cpus.c \ + $(src)/arch/x86/secondary.o \ $(obj)/coreboot.vpd: $(Q)printf " BUILD DUMMY VPD\n" diff --git a/mainboard/kontron/986lcd-m/dts b/mainboard/kontron/986lcd-m/dts index a9e34e2bc9fb..a9d90eed7989 100644 --- a/mainboard/kontron/986lcd-m/dts +++ b/mainboard/kontron/986lcd-m/dts @@ -152,7 +152,6 @@ end disabled; }; pci@2,0 { /* Onboard VGA. */ - rom_address = "0xfff00000"; /* Shouldn't this be a lar path? */ }; pci@2,1 { /* Display controller. */ }; @@ -169,8 +168,8 @@ end /config/("southbridge/intel/i82801gx/pcie3.dts"); }; pci@1c,3{ disabled; }; /* PCIe port 4 */ - pci@1c,4{ disabled; }; /* PCIe port 5 */ - pci@1c,5{ disabled; }; /* PCIe port 6 */ + pci@1c,4{ /config/("southbridge/intel/i82801gx/pcie5.dts"); }; /* PCIe port 5 */ + pci@1c,5{ /config/("southbridge/intel/i82801gx/pcie6.dts"); }; /* PCIe port 6 */ pci@1d,0{ /config/("southbridge/intel/i82801gx/usb1.dts"); }; diff --git a/mainboard/kontron/986lcd-m/initram.c b/mainboard/kontron/986lcd-m/initram.c index b1c2d8ba3833..b8771126796e 100644 --- a/mainboard/kontron/986lcd-m/initram.c +++ b/mainboard/kontron/986lcd-m/initram.c @@ -226,8 +226,5 @@ int main(void) } #endif MCHBAR16(SSKPD) = 0xCAFE; - - init_cpus(boot_mode, sysinfo); - return 0; } |