summaryrefslogtreecommitdiff
path: root/src/arch/i386/init/car.S
diff options
context:
space:
mode:
authorRonald G. minnich <rminnich@gmail.com>2009-06-16 15:02:52 +0000
committerRonald G. Minnich <rminnich@gmail.com>2009-06-16 15:02:52 +0000
commitd41de2ea7a65242f5c95e578d99cf46cd23920dd (patch)
tree45e8cd3a261bee5bb6edd3dcd9ef3f19ba4773b8 /src/arch/i386/init/car.S
parent3ba18a67eb4e4bea8801633517ee2b56e471c648 (diff)
These changes implement car in qemu. The implementation is in several
ways superior to v3, while lacking its completeness. But, one nice thing: no more included .S or .c files. It's all separate compilation. That should allow our Makefiles to work much better. Note that the current non-CAR implementation is the default and continues to work (tested FILO boot to Linux on both CAR and non-CAR). Index: src/mainboard/emulation/qemu-x86/Config.lb Change this to be sensitive to USE_DCACHE_RAM. All settings etc. that depend on this variable are grouped in one if, and the other parts (romcc etc.) are in the else. This change is a model of how we should be able to do other motherboards. Index: src/mainboard/emulation/qemu-x86/Options.lb add needed options. Index: src/mainboard/emulation/qemu-x86/failover.c remove code inclusion from this not-yet-used file. Index: src/mainboard/emulation/qemu-x86/rom.c This is the entry point for the rom-based code. Called stage1.c in v3. Index: src/lib/Config.lb change initobject to a .o from a .c; this fixed a build problem. Index: src/pc80/serial.c make uart_init non-static. Index: src/pc80/Config.lb add initobject Index: src/arch/i386/init/entry.S Entry point. Unify a bunch of files that were fiddly lttle includes. From v3. Index: src/arch/i386/init/ldscript.ld new file. The goal is to hang all init changes for CAR here, to minimize other changes to any other ldscript. Besides, putting this in init makes sense; entry and car are manage init. Index: src/arch/i386/init/car.S generic i386 car code from v3. Index: src/arch/i386/init/ldscript_fallback_cbfs.lb Fix what looks like a bug: this was not including the init.text section. Index: targets/emulation/qemu-x86/Config.lb push up the console loglevel. qemu is for debugging so we might as well get all the debugging we can. Index: targets/emulation/qemu-x86/Config-car.lb For CAR bullds. Signed-off-by: Ronald G. minnich <rminnich@gmail.com> Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4357 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/i386/init/car.S')
-rw-r--r--src/arch/i386/init/car.S357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/arch/i386/init/car.S b/src/arch/i386/init/car.S
new file mode 100644
index 0000000000..94ffc648c5
--- /dev/null
+++ b/src/arch/i386/init/car.S
@@ -0,0 +1,357 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com>
+ * Copyright (C) 2005 Eswar Nallusamy, LANL
+ * Copyright (C) 2005 Tyan
+ * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan)
+ * Copyright (C) 2007 coresystems GmbH
+ * (Written by Stefan Reinauer <stepan@coresystems.de> for coresystems GmbH)
+ * Copyright (C) 2008 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Init code - Switch CPU to protected mode and enable Cache-as-Ram (CAR). */
+
+#include <arch/intel.h>
+
+#define ROM_CODE_SEG 0x08
+#define ROM_DATA_SEG 0x10
+
+#define CACHE_RAM_CODE_SEG 0x18
+#define CACHE_RAM_DATA_SEG 0x20
+
+ /* When we come here we are in protected mode. We expand the stack
+ * and copy the data segment from ROM to the memory.
+ *
+ * After that, we call the chipset bootstrap routine that
+ * does what is left of the chipset initialization.
+ *
+ * NOTE: Aligned to 4 so that we are sure that the prefetch
+ * cache will be reloaded.
+ */
+ .section .rom.text
+ .align 4
+ .globl protected_stage0
+protected_stage0:
+ lgdt %cs:gdtptr
+ ljmp $ROM_CODE_SEG, $__protected_stage0
+
+.globl __protected_stage0
+__protected_stage0:
+ /* Save the BIST result. */
+ movl %eax, %ebp
+
+ intel_chip_post_macro(0x01)
+
+ movw $ROM_DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movw %ax, %fs
+ movw %ax, %gs
+
+ /* Restore the BIST value to %eax. */
+ movl %ebp, %eax
+
+.align 4
+
+/* disable HyperThreading is done by eswar
+ * the other is very similar to the AMD CAR, except remove amd specific msr
+ */
+
+#define CacheSize DCACHE_RAM_SIZE
+#define CacheBase DCACHE_RAM_BASE
+
+#include <cpu/x86/mtrr.h>
+
+ /* Save the BIST result */
+ movl %eax, %ebp
+
+CacheAsRam:
+ /* Check whether the processor has HT capability */
+ movl $01, %eax
+ cpuid
+ btl $28, %edx
+ jnc NotHtProcessor
+ bswapl %ebx
+ cmpb $01, %bh
+ jbe NotHtProcessor
+
+ /* It is a HT processor; Send SIPI to the other logical processor
+ * within this processor so that the CAR related common system
+ * registers are programmed accordingly
+ */
+
+ /* Use some register that is common to both logical processors
+ * as semaphore. Refer Appendix B, Vol.3
+ */
+
+ xorl %eax, %eax
+ xorl %edx, %edx
+ movl $0x250, %ecx
+ wrmsr
+
+ /* Figure out the logical AP's APIC ID; the following logic will work
+ * only for processors with 2 threads.
+ *
+ * Refer to Vol 3. Table 7-1 for details about this logic
+ */
+ movl $0xFEE00020, %esi
+ movl (%esi), %ebx
+ andl $0xFF000000, %ebx
+ bswapl %ebx
+ btl $0, %ebx
+ jnc LogicalAP0
+ andb $0xFE, %bl
+ jmp SendSIPI
+LogicalAP0:
+ orb $0x01, %bl
+SendSIPI:
+ bswapl %ebx /* ebx - logical AP's APIC ID */
+
+ /* Fill up the IPI command registers in the Local APIC mapped to
+ * default address and issue SIPI to the other logical processor
+ * within this processor die.
+ */
+
+RetrySIPI:
+ movl %ebx, %eax
+ movl $0xFEE00310, %esi
+ movl %eax, (%esi)
+
+ /* SIPI vector - F900:0000 */
+ movl $0x000006F9, %eax
+ movl $0xFEE00300, %esi
+ movl %eax, (%esi)
+
+ movl $0x30, %ecx
+SIPIDelay:
+ pause
+ decl %ecx
+ jnz SIPIDelay
+
+ movl (%esi), %eax
+ andl $0x00001000, %eax
+ jnz RetrySIPI
+
+ /* Wait for the Logical AP to complete initialization */
+LogicalAPSIPINotdone:
+ movl $0x250, %ecx
+ rdmsr
+ orl %eax, %eax
+ jz LogicalAPSIPINotdone
+
+
+
+NotHtProcessor:
+ /* Set the default memory type and enable fixed and variable MTRRs */
+ movl $MTRRdefType_MSR, %ecx
+ xorl %edx, %edx
+ /* Enable Variable and Fixed MTRRs */
+ movl $0x00000c00, %eax
+ wrmsr
+
+ /* Clear all MTRRs */
+ xorl %edx, %edx
+ movl $fixed_mtrr_msr, %esi
+
+clear_fixed_var_mtrr:
+ lodsl (%esi), %eax
+ testl %eax, %eax
+ jz clear_fixed_var_mtrr_out
+
+ movl %eax, %ecx
+ xorl %eax, %eax
+ wrmsr
+
+ jmp clear_fixed_var_mtrr
+clear_fixed_var_mtrr_out:
+
+/* 0x06 is the WB IO type for a given 4k segment.
+ * segs is the number of 4k segments in the area of the particular
+ * register we want to use for CAR.
+ * reg is the register where the IO type should be stored.
+ */
+.macro extractmask segs, reg
+.if \segs <= 0
+ /* The xorl here is superfluous because at the point of first execution
+ * of this macro, %eax and %edx are cleared. Later invocations of this
+ * macro will have a monotonically increasing segs parameter.
+ */
+ xorl \reg, \reg
+.elseif \segs == 1
+ movl $0x06000000, \reg /* WB IO type */
+.elseif \segs == 2
+ movl $0x06060000, \reg /* WB IO type */
+.elseif \segs == 3
+ movl $0x06060600, \reg /* WB IO type */
+.elseif \segs >= 4
+ movl $0x06060606, \reg /* WB IO type */
+.endif
+.endm
+
+/* size is the cache size in bytes we want to use for CAR.
+ * windowoffset is the 32k-aligned window into CAR size
+ */
+.macro simplemask carsize, windowoffset
+/* DO NOT CHANGE THE FORMATTING of the two lines below! Whitespace is
+ * interpreted as an argument delimiter by some versions of GNU as. */
+ extractmask (((\carsize-\windowoffset)/0x1000)-4), %eax
+ extractmask (((\carsize-\windowoffset)/0x1000)), %edx
+.endm
+
+#if CacheSize > 0x10000
+#error Invalid CAR size, must be at most 64k.
+#endif
+#if CacheSize < 0x1000
+#error Invalid CAR size, must be at least 4k. This is a processor limitation.
+#endif
+#if (CacheSize & (0x1000 - 1))
+#error Invalid CAR size, is not a multiple of 4k. This is a processor limitation.
+#endif
+
+#if CacheSize > 0x8000
+ /* enable caching for 32K-64K using fixed mtrr */
+ movl $0x268, %ecx /* fix4k_c0000*/
+ simplemask CacheSize, 0x8000
+ wrmsr
+#endif
+
+ /* enable caching for 0-32K using fixed mtrr */
+ movl $0x269, %ecx /* fix4k_c8000*/
+ simplemask CacheSize, 0
+ wrmsr
+
+#if defined(CONFIG_XIP_ROM_SIZE) && defined(CONFIG_XIP_ROM_BASE)
+ /* enable write base caching so we can do execute in place
+ * on the flash rom.
+ */
+ movl $0x202, %ecx
+ xorl %edx, %edx
+ movl $(XIP_ROM_BASE | MTRR_TYPE_WRBACK), %eax
+ wrmsr
+
+ movl $0x203, %ecx
+ movl $0x0000000f, %edx
+ movl $(~(XIP_ROM_SIZE - 1) | 0x800), %eax
+ wrmsr
+#endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
+
+ /* enable cache */
+ movl %cr0, %eax
+ andl $0x9fffffff,%eax
+ movl %eax, %cr0
+
+ /* Read the range with lodsl*/
+ movl $CacheBase, %esi
+ cld
+ movl $(CacheSize>>2), %ecx
+ rep lodsl
+
+ /* Clear the range */
+ movl $CacheBase, %edi
+ movl $(CacheSize>>2), %ecx
+ xorl %eax, %eax
+ rep stosl
+
+
+ /* TODO: make this a config variable */
+#if CONFIG_CARTEST
+ /* check the cache as ram */
+ movl $CacheBase, %esi
+ movl $(CacheSize>>2), %ecx
+.xin1:
+ movl %esi, %eax
+ movl %eax, (%esi)
+ decl %ecx
+ je .xout1
+ add $4, %esi
+ jmp .xin1
+.xout1:
+
+ movl $CacheBase, %esi
+// movl $(CacheSize>>2), %ecx
+ movl $4, %ecx
+.xin1x:
+ movl %esi, %eax
+
+ movl $0x4000, %edx
+ movb %ah, %al
+.testx1:
+ outb %al, $0x80
+ decl %edx
+ jnz .testx1
+
+ movl (%esi), %eax
+ cmpb 0xff, %al
+ je .xin2 /* dont show */
+
+ movl $0x4000, %edx
+.testx2:
+ outb %al, $0x80
+ decl %edx
+ jnz .testx2
+
+.xin2: decl %ecx
+ je .xout1x
+ add $4, %esi
+ jmp .xin1x
+.xout1x:
+
+#endif
+
+ movl $(CacheBase+CacheSize-4), %eax
+ movl %eax, %esp
+
+ /* Load a different set of data segments */
+ movw $CACHE_RAM_DATA_SEG, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+
+lout:
+ /* Store zero for the pointer to the global variables. */
+ pushl $0
+
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+
+ /* We need to set ebp? No need. */
+ movl %esp, %ebp
+
+ /* Third parameter: cpu #: 0 == BSP all other are APs.
+ * 0 until SMP support is added.
+ */
+ pushl $0
+ /* Second parameter: init_detected */
+ /* Store zero for the unused init_detected parameter. */
+ pushl $0
+ /* First parameter: bist */
+ pushl %eax
+ call main
+ /* We will not go back. */
+
+fixed_mtrr_msr:
+ .long 0x250, 0x258, 0x259
+ .long 0x268, 0x269, 0x26A
+ .long 0x26B, 0x26C, 0x26D
+ .long 0x26E, 0x26F
+var_mtrr_msr:
+ .long 0x200, 0x201, 0x202, 0x203
+ .long 0x204, 0x205, 0x206, 0x207
+ .long 0x208, 0x209, 0x20A, 0x20B
+ .long 0x20C, 0x20D, 0x20E, 0x20F
+ .long 0x000 /* NULL, end of table */