Author: hailfinger Date: 2008-10-07 01:06:32 +0200 (Tue, 07 Oct 2008) New Revision: 899
Added: coreboot-v3/arch/x86/i586/ coreboot-v3/arch/x86/i586/stage0.S Removed: coreboot-v3/arch/x86/intel/ coreboot-v3/arch/x86/stage0_i586.S Modified: coreboot-v3/arch/x86/Makefile Log: Move the generic intel x86 init code in arch/x86/stage0_i586.S to arch/x86/i586/stage0.S to make it consistent with the other variants of that code. Clean up two superfluous rules from arch/x86/Makefile which were needed before. That makefile change also fixes a latent bug which may have been exposed by later additions to the tree.
Compile tested on all arches.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Acked-by: Peter Stuge peter@stuge.se
Modified: coreboot-v3/arch/x86/Makefile =================================================================== --- coreboot-v3/arch/x86/Makefile 2008-10-06 17:17:40 UTC (rev 898) +++ coreboot-v3/arch/x86/Makefile 2008-10-06 23:06:32 UTC (rev 899) @@ -112,7 +112,7 @@ endif
ifeq ($(CONFIG_CPU_I586),y) - STAGE0_CAR_OBJ = stage0_i586.o + STAGE0_CAR_OBJ = i586/stage0.o else ifeq ($(CONFIG_CPU_AMD_GEODELX),y) STAGE0_CAR_OBJ = geodelx/stage0.o @@ -243,15 +243,7 @@ $(Q)$(CC) $(INITCFLAGS) -c $< -o $@ # Building asm stub. -$(obj)/arch/x86/stage0%.o: $(src)/arch/x86/stage0%.S - $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n" - $(Q)$(CC) -E $(COREBOOTINCLUDE) $< \ - -o $(obj)/arch/x86/stage0_asm.s -DBOOTBLK=0x1f00 \ - -DRESRVED=0xf0 -DDATE="`date +%Y/%m/%d`" - $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n" - $(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@ - -$(obj)/arch/x86/geodelx/stage0.o: $(src)/arch/x86/geodelx/stage0.S +$(obj)/arch/x86/%/stage0.o: $(src)/arch/x86/%/stage0.S $(Q)mkdir -p $(dir $@) $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n" $(Q)$(CC) -E $(COREBOOTINCLUDE) $< \ @@ -260,18 +252,6 @@ $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n" $(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@
- -# NOTE HACK. Stefan will fix this :-) -$(obj)/arch/x86/amd/stage0.o: $(src)/arch/x86/amd/stage0.S - $(Q)mkdir -p $(dir $@) - $(Q)printf " CC $(subst $(shell pwd)/,,$(@))\n" - $(Q)$(CC) -E $(COREBOOTINCLUDE) $< \ - -I $(src)/include/arch/x86/amd/k8 \ - -o $(obj)/arch/x86/stage0_asm.s -DBOOTBLK=0x1f00 \ - -DRESRVED=0xf0 -DDATE="`date +%Y/%m/%d`" - $(Q)printf " AS $(subst $(shell pwd)/,,$(@))\n" - $(Q)$(AS) $(obj)/arch/x86/stage0_asm.s -o $@ - $(obj)/coreboot.initram $(obj)/coreboot.initram.map: $(obj)/stage0.init $(obj)/stage0-prefixed.o $(INITRAM_SRC) $(Q)printf " CC $(subst $(shell pwd)/,,$(@)) (XIP)\n" $(Q)$(CC) $(INITCFLAGS) -fPIE -c -combine $(COMBINEFLAGS) $(INITRAM_SRC) -o $(obj)/coreboot.initram_partiallylinked.o
Copied: coreboot-v3/arch/x86/i586/stage0.S (from rev 898, coreboot-v3/arch/x86/stage0_i586.S) =================================================================== --- coreboot-v3/arch/x86/i586/stage0.S (rev 0) +++ coreboot-v3/arch/x86/i586/stage0.S 2008-10-06 23:06:32 UTC (rev 899) @@ -0,0 +1,498 @@ +## +## 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) +## +## 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 pmode and enable cache as ram. + +#include <macros.h> + +#define ROM_CODE_SEG 0x08 +#define ROM_DATA_SEG 0x10 + +#define CACHE_RAM_CODE_SEG 0x18 +#define CACHE_RAM_DATA_SEG 0x20 + .code16 + .globl _stage0 +_stage0: + cli + + /* save the BIST result */ + movl %eax, %ebp; + + /* thanks to kmliu@sis.tw.com for this TLB fix */ + /* IMMEDIATELY invalidate the translation lookaside buffer before + * executing any further code. Even though paging is disabled we + * could still get false address translations due to the TLB if we + * didn't invalidate it. + */ + + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB */ + + /* switch to protected mode */ + + /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux) + * using BFD version 2.15.94.0.2.2 20041220 this works fine without all + * the ld hackery and other things. So leave it as is with this comment. + */ + + data32 lgdt %cs:gdtptr + + movl %cr0, %eax + andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ + orl $0x60000001, %eax /* CD, NW, PE = 1 */ + movl %eax, %cr0 + + /* Restore BIST result */ + movl %ebp, %eax + + + // port80_post (0x23) /* post 0x01 */ + /* Now we are in protected mode. Jump to a 32 bit code segment. */ + data32 ljmp $ROM_CODE_SEG, $protected_stage0 + /* I am leaving this weird jump in here in the event that future gas bugs force it to be used. */ + #.byte 0x66 + .code32 + #ljmp $ROM_CODE_SEG, $protected_stage0 + + #.code16 + .align 4 + .globl gdt16 +gdt16 = . - _stage0 +gdt16x: + .word gdt16xend - gdt16x -1 /* compute the table limit */ + .long gdt16x + .word 0 + + /* selgdt 0x08, flat code segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x9b, 0xcf, 0x00 + + /* selgdt 0x10,flat data segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x93, 0xcf, 0x00 +gdt16xend: + + /* From now on we are 32bit */ + + .code32 + +/* We have two gdts where we could have one. That is ok. + * + * Let's not worry about this -- optimizing gdt is pointless since we're + * only in it for a little bit. + * + * BTW note the trick below: The GDT points to ITSELF, and the first good + * descriptor is at offset 8. So you word-align the table, and then because + * you chose 8, you get a nice 64-bit aligned GDT entry, which is good as + * this is the size of the entry. + * Just in case you ever wonder why people do this. + */ + .align 4 + .globl gdtptr + .globl gdt_limit +gdt_limit = gdt_end - gdt - 1 /* compute the table limit */ + +gdt: +gdtptr: + .word gdt_end - gdt -1 /* compute the table limit */ + .long gdt /* we know the offset */ + .word 0 + + /* selgdt 0x08, flat code segment */ + .word 0xffff, 0x0000 + .byte 0x00, 0x9b, 0xcf, 0x00 + + /* 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: + +/* + * When we come here we are in protected mode. We expand + * the stack and copies 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. + */ + + .align 4 + .globl protected_stage0 +protected_stage0: + //This code was used by v2. TODO + lgdt %cs:gdtptr + ljmp $ROM_CODE_SEG, $__protected_stage0 + +.globl __protected_stage0 +__protected_stage0: + /* Save the BIST value */ + movl %eax, %ebp + + port80_post (0x01) /* post 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 + + + +/* We will use 4Kbytes only for cache as ram. This is + * enough to fit in our stack. + * + * disable HyperThreading is done by eswar + * the other is very similar to the AMD CAR, except remove amd specific msr + */ + +#define CacheSize CONFIG_CARSIZE + +#define CacheBase CONFIG_CARBASE + +#define ASSEMBLY +#include "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 +.elseif \segs == 2 + movl $0x06060000, \reg +.elseif \segs == 3 + movl $0x06060600, \reg +.elseif \segs >= 4 + movl $0x06060606, \reg +.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. */ + movl $0, %eax + pushl %eax + + /* Store zero for the unused init_detected parameter. */ + pushl %eax + + /* Restore the BIST result */ + movl %ebp, %eax + /* We need to set ebp ? No need */ + movl %esp, %ebp + pushl %eax /* bist */ + call stage1_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 */ + +# Reset vector. + +/* + RVECTOR: size of reset vector, default is 0x10 + RESRVED: size of vpd code, default is 0xf0 + BOOTBLK: size of bootblock code, default is 0x1f00 (8k-256b) +*/ + +SEGMENT_SIZE = 0x10000 +RVECTOR = 0x00010 +# Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here. +# I think we should leave it this way forever, as the bugs come and +# go -- and come again. +# .code16 +# .section ".rom.text" +.section ".reset", "ax" + .globl _resetjump +_resetjump: + /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */ +# jmp _stage0 + .byte 0xe9 + .int _stage0 - ( . + 2 ) + /* Note: The above jump is hand coded to work around bugs in binutils. + * 5 byte are used for a 3 byte instruction. This works because x86 + * is little endian and allows us to use supported 32bit relocations + * instead of the weird 16 bit relocations that binutils does not + * handle consistenly between versions because they are used so rarely. + */ +.byte 0 + +# Date? ID string? We might want to put something else in here. +.ascii DATE + +# Checksum. +#.word 0
Deleted: coreboot-v3/arch/x86/stage0_i586.S =================================================================== --- coreboot-v3/arch/x86/stage0_i586.S 2008-10-06 17:17:40 UTC (rev 898) +++ coreboot-v3/arch/x86/stage0_i586.S 2008-10-06 23:06:32 UTC (rev 899) @@ -1,498 +0,0 @@ -## -## 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) -## -## 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 pmode and enable cache as ram. - -#include <macros.h> - -#define ROM_CODE_SEG 0x08 -#define ROM_DATA_SEG 0x10 - -#define CACHE_RAM_CODE_SEG 0x18 -#define CACHE_RAM_DATA_SEG 0x20 - .code16 - .globl _stage0 -_stage0: - cli - - /* save the BIST result */ - movl %eax, %ebp; - - /* thanks to kmliu@sis.tw.com for this TLB fix */ - /* IMMEDIATELY invalidate the translation lookaside buffer before - * executing any further code. Even though paging is disabled we - * could still get false address translations due to the TLB if we - * didn't invalidate it. - */ - - xorl %eax, %eax - movl %eax, %cr3 /* Invalidate TLB */ - - /* switch to protected mode */ - - /* NOTE: With GNU assembler version 2.15.94.0.2.2 (i386-redhat-linux) - * using BFD version 2.15.94.0.2.2 20041220 this works fine without all - * the ld hackery and other things. So leave it as is with this comment. - */ - - data32 lgdt %cs:gdtptr - - movl %cr0, %eax - andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ - orl $0x60000001, %eax /* CD, NW, PE = 1 */ - movl %eax, %cr0 - - /* Restore BIST result */ - movl %ebp, %eax - - - // port80_post (0x23) /* post 0x01 */ - /* Now we are in protected mode. Jump to a 32 bit code segment. */ - data32 ljmp $ROM_CODE_SEG, $protected_stage0 - /* I am leaving this weird jump in here in the event that future gas bugs force it to be used. */ - #.byte 0x66 - .code32 - #ljmp $ROM_CODE_SEG, $protected_stage0 - - #.code16 - .align 4 - .globl gdt16 -gdt16 = . - _stage0 -gdt16x: - .word gdt16xend - gdt16x -1 /* compute the table limit */ - .long gdt16x - .word 0 - - /* selgdt 0x08, flat code segment */ - .word 0xffff, 0x0000 - .byte 0x00, 0x9b, 0xcf, 0x00 - - /* selgdt 0x10,flat data segment */ - .word 0xffff, 0x0000 - .byte 0x00, 0x93, 0xcf, 0x00 -gdt16xend: - - /* From now on we are 32bit */ - - .code32 - -/* We have two gdts where we could have one. That is ok. - * - * Let's not worry about this -- optimizing gdt is pointless since we're - * only in it for a little bit. - * - * BTW note the trick below: The GDT points to ITSELF, and the first good - * descriptor is at offset 8. So you word-align the table, and then because - * you chose 8, you get a nice 64-bit aligned GDT entry, which is good as - * this is the size of the entry. - * Just in case you ever wonder why people do this. - */ - .align 4 - .globl gdtptr - .globl gdt_limit -gdt_limit = gdt_end - gdt - 1 /* compute the table limit */ - -gdt: -gdtptr: - .word gdt_end - gdt -1 /* compute the table limit */ - .long gdt /* we know the offset */ - .word 0 - - /* selgdt 0x08, flat code segment */ - .word 0xffff, 0x0000 - .byte 0x00, 0x9b, 0xcf, 0x00 - - /* 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: - -/* - * When we come here we are in protected mode. We expand - * the stack and copies 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. - */ - - .align 4 - .globl protected_stage0 -protected_stage0: - //This code was used by v2. TODO - lgdt %cs:gdtptr - ljmp $ROM_CODE_SEG, $__protected_stage0 - -.globl __protected_stage0 -__protected_stage0: - /* Save the BIST value */ - movl %eax, %ebp - - port80_post (0x01) /* post 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 - - - -/* We will use 4Kbytes only for cache as ram. This is - * enough to fit in our stack. - * - * disable HyperThreading is done by eswar - * the other is very similar to the AMD CAR, except remove amd specific msr - */ - -#define CacheSize CONFIG_CARSIZE - -#define CacheBase CONFIG_CARBASE - -#define ASSEMBLY -#include "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 -.elseif \segs == 2 - movl $0x06060000, \reg -.elseif \segs == 3 - movl $0x06060600, \reg -.elseif \segs >= 4 - movl $0x06060606, \reg -.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. */ - movl $0, %eax - pushl %eax - - /* Store zero for the unused init_detected parameter. */ - pushl %eax - - /* Restore the BIST result */ - movl %ebp, %eax - /* We need to set ebp ? No need */ - movl %esp, %ebp - pushl %eax /* bist */ - call stage1_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 */ - -# Reset vector. - -/* - RVECTOR: size of reset vector, default is 0x10 - RESRVED: size of vpd code, default is 0xf0 - BOOTBLK: size of bootblock code, default is 0x1f00 (8k-256b) -*/ - -SEGMENT_SIZE = 0x10000 -RVECTOR = 0x00010 -# Due to YET ANOTHER BUG in GNU bintools, you can NOT have a code16 here. -# I think we should leave it this way forever, as the bugs come and -# go -- and come again. -# .code16 -# .section ".rom.text" -.section ".reset", "ax" - .globl _resetjump -_resetjump: - /* GNU bintools bugs again. This jumps to stage0 - 2. Sigh. */ -# jmp _stage0 - .byte 0xe9 - .int _stage0 - ( . + 2 ) - /* Note: The above jump is hand coded to work around bugs in binutils. - * 5 byte are used for a 3 byte instruction. This works because x86 - * is little endian and allows us to use supported 32bit relocations - * instead of the weird 16 bit relocations that binutils does not - * handle consistenly between versions because they are used so rarely. - */ -.byte 0 - -# Date? ID string? We might want to put something else in here. -.ascii DATE - -# Checksum. -#.word 0