Author: rminnich Date: 2009-03-11 17:17:37 +0100 (Wed, 11 Mar 2009) New Revision: 1145
Modified: coreboot-v3/arch/x86/intel/core2/init_cpus.c coreboot-v3/arch/x86/secondary.S coreboot-v3/device/pci_device.c coreboot-v3/device/pci_rom.c coreboot-v3/include/lib.h coreboot-v3/lib/stage2.c coreboot-v3/mainboard/kontron/986lcd-m/Makefile coreboot-v3/mainboard/kontron/986lcd-m/dts coreboot-v3/mainboard/kontron/986lcd-m/initram.c Log: 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
Modified: coreboot-v3/arch/x86/intel/core2/init_cpus.c =================================================================== --- coreboot-v3/arch/x86/intel/core2/init_cpus.c 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/arch/x86/intel/core2/init_cpus.c 2009-03-11 16:17:37 UTC (rev 1145) @@ -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 @@ 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 @@ * 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 @@ 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 @@ /* we compile the secondary start code such that this looks like a stack frame */ struct stack { + u32 data[16384/sizeof(u32) - 7]; + struct spinlock *start_cpu_lock; + struct atomic *active_cpus; + u32 apicid; + u32 index; u32 post; - u32 index; - u32 apicid; - struct atomic *active_cpus; - struct spinlock *start_cpu_lock; u32 callerpc; - u32 data[16384/sizeof(u32) - 7]; };
struct stackmem { @@ -377,18 +384,25 @@ 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 @@ 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 @@ 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 @@ * @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 @@ // 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);
Modified: coreboot-v3/arch/x86/secondary.S =================================================================== --- coreboot-v3/arch/x86/secondary.S 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/arch/x86/secondary.S 2009-03-11 16:17:37 UTC (rev 1145) @@ -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 @@ .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 @@ /* 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 @@ /* 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:
Modified: coreboot-v3/device/pci_device.c =================================================================== --- coreboot-v3/device/pci_device.c 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/device/pci_device.c 2009-03-11 16:17:37 UTC (rev 1145) @@ -1304,7 +1304,8 @@ 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; }
Modified: coreboot-v3/device/pci_rom.c =================================================================== --- coreboot-v3/device/pci_rom.c 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/device/pci_rom.c 2009-03-11 16:17:37 UTC (rev 1145) @@ -47,7 +47,7 @@ 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");
Modified: coreboot-v3/include/lib.h =================================================================== --- coreboot-v3/include/lib.h 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/include/lib.h 2009-03-11 16:17:37 UTC (rev 1145) @@ -52,4 +52,10 @@ /* 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 */
Modified: coreboot-v3/lib/stage2.c =================================================================== --- coreboot-v3/lib/stage2.c 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/lib/stage2.c 2009-03-11 16:17:37 UTC (rev 1145) @@ -27,8 +27,40 @@ #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. * * Coreboot is divided into pre-DRAM part and DRAM part. The stages before @@ -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 @@ 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();
Modified: coreboot-v3/mainboard/kontron/986lcd-m/Makefile =================================================================== --- coreboot-v3/mainboard/kontron/986lcd-m/Makefile 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/mainboard/kontron/986lcd-m/Makefile 2009-03-11 16:17:37 UTC (rev 1145) @@ -23,18 +23,17 @@ 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_CHIPSET_SRC= \ + $(src)/northbridge/intel/i945//reset_test.c \ + $(src)/arch/x86/intel/core2/init_cpus.c \ + $(src)/arch/x86/secondary.o \
-STAGE2_MAINBOARD_SRC = - $(obj)/coreboot.vpd: $(Q)printf " BUILD DUMMY VPD\n" $(Q)dd if=/dev/zero of=$(obj)/coreboot.vpd bs=256 count=1 $(SILENT)
Modified: coreboot-v3/mainboard/kontron/986lcd-m/dts =================================================================== --- coreboot-v3/mainboard/kontron/986lcd-m/dts 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/mainboard/kontron/986lcd-m/dts 2009-03-11 16:17:37 UTC (rev 1145) @@ -152,7 +152,6 @@ 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 @@ /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"); };
Modified: coreboot-v3/mainboard/kontron/986lcd-m/initram.c =================================================================== --- coreboot-v3/mainboard/kontron/986lcd-m/initram.c 2009-03-05 21:28:56 UTC (rev 1144) +++ coreboot-v3/mainboard/kontron/986lcd-m/initram.c 2009-03-11 16:17:37 UTC (rev 1145) @@ -226,8 +226,5 @@ } #endif MCHBAR16(SSKPD) = 0xCAFE; - - init_cpus(boot_mode, sysinfo); - return 0; }