From 0308313e07caf60ac77c416a448026c09351fe5d Mon Sep 17 00:00:00 2001 From: Kyösti Mälkki Date: Sun, 22 Nov 2020 00:34:13 +0200 Subject: cpu/x86: Link entry16.inc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I78ecd15716169b58cf6696ff8c5069ac2d5038ef Signed-off-by: Kyösti Mälkki Reviewed-on: https://review.coreboot.org/c/coreboot/+/47967 Reviewed-by: Angel Pons Reviewed-by: Arthur Heymans Tested-by: build bot (Jenkins) --- src/cpu/x86/16bit/entry16.inc | 138 ---------------------------------------- src/cpu/x86/32bit/entry32.inc | 1 + src/cpu/x86/Makefile.inc | 2 + src/cpu/x86/entry16.S | 142 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+), 138 deletions(-) delete mode 100644 src/cpu/x86/16bit/entry16.inc create mode 100644 src/cpu/x86/entry16.S (limited to 'src/cpu/x86') diff --git a/src/cpu/x86/16bit/entry16.inc b/src/cpu/x86/16bit/entry16.inc deleted file mode 100644 index 5e90da1413..0000000000 --- a/src/cpu/x86/16bit/entry16.inc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This software and ancillary information (herein called SOFTWARE) - * called LinuxBIOS is made available under the terms described here. - * - * The SOFTWARE has been approved for release with associated - * LA-CC Number 00-34. Unless otherwise indicated, this SOFTWARE has - * been authored by an employee or employees of the University of - * California, operator of the Los Alamos National Laboratory under - * Contract No. W-7405-ENG-36 with the U.S. Department of Energy. - * - * The U.S. Government has rights to use, reproduce, and distribute this - * SOFTWARE. The public may copy, distribute, prepare derivative works - * and publicly display this SOFTWARE without charge, provided that this - * Notice and any statement of authorship are reproduced on all copies. - * - * Neither the Government nor the University makes any warranty, express - * or implied, or assumes any liability or responsibility for the use of - * this SOFTWARE. If SOFTWARE is modified to produce derivative works, - * such modified SOFTWARE should be clearly marked, so as not to confuse - * it with the version available from LANL. - * - */ - - -/* Start code to put an i386 or later processor into 32-bit protected mode. - */ - -#include -#include - -/* Symbol _start16bit must be aligned to 4kB to start AP CPUs with - * Startup IPI message without RAM. - */ -.align 4096 -.code16 -.globl _start16bit -.type _start16bit, @function - -_start16bit: - cli - /* Save the BIST result */ - movl %eax, %ebp -#if !CONFIG(NO_EARLY_BOOTBLOCK_POSTCODES) - post_code(POST_RESET_VECTOR_CORRECT) -#endif - - /* IMMEDIATELY invalidate the translation lookaside buffer (TLB) 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. Thanks to kmliu@sis.com.tw for this TLB fix. - */ - - xorl %eax, %eax - movl %eax, %cr3 /* Invalidate TLB*/ - - /* Invalidating the cache here seems to be a bad idea on - * modern processors. Don't. - * If we are hyperthreaded or we have multiple cores it is bad, - * for SMP startup. On Opterons it causes a 5 second delay. - * Invalidating the cache was pure paranoia in any event. - * If your CPU needs it you can write a CPU dependent version of - * entry16.inc. - */ - - /* Note: gas handles memory addresses in 16 bit code very poorly. - * In particular it doesn't appear to have a directive allowing you - * associate a section or even an absolute offset with a segment register. - * - * This means that anything except cs:ip relative offsets are - * a real pain in 16 bit mode. And explains why it is almost - * impossible to get gas to do lgdt correctly. - * - * One way to work around this is to have the linker do the - * math instead of the assembler. This solves the very - * practical problem of being able to write code that can - * be relocated. - * - * An lgdt call before we have memory enabled cannot be - * position independent, as we cannot execute a call - * instruction to get our current instruction pointer. - * So while this code is relocatable it isn't arbitrarily - * relocatable. - * - * The criteria for relocation have been relaxed to their - * utmost, so that we can use the same code for both - * our initial entry point and startup of the second CPU. - * The code assumes when executing at _start16bit that: - * (((cs & 0xfff) == 0) and (ip == _start16bit & 0xffff)) - * or - * ((cs == anything) and (ip == 0)). - * - * The restrictions in reset16.inc mean that _start16bit initially - * must be loaded at or above 0xffff0000 or below 0x100000. - * - * The linker scripts computes gdtptr16_offset by simply returning - * the low 16 bits. This means that the initial segment used - * when start is called must be 64K aligned. This should not - * restrict the address as the ip address can be anything. - * - * Also load an IDT with NULL limit to prevent the 16bit IDT being used - * in protected mode before c_start.S sets up a 32bit IDT when entering - * RAM stage. In practise: CPU will shutdown on any exception. - * See IA32 manual Vol 3A 19.26 Interrupts. - */ - - movw %cs, %ax - shlw $4, %ax - movw $nullidt_offset, %bx - subw %ax, %bx - lidt %cs:(%bx) - movw $gdtptr_offset, %bx - subw %ax, %bx - lgdtl %cs:(%bx) - - 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 to %eax */ - movl %ebp, %eax - - /* Now that we are in protected mode jump to a 32 bit code segment. */ - ljmpl $ROM_CODE_SEG, $__protected_start - - /** - * The gdt is defined in gdt_init.S, it has a 4 Gb code segment - * at 0x08, and a 4 GB data segment at 0x10; - */ -__gdtptr: - .long gdtptr - -.align 4 -.globl nullidt -nullidt: - .word 0 /* limit */ - .long 0 - .word 0 diff --git a/src/cpu/x86/32bit/entry32.inc b/src/cpu/x86/32bit/entry32.inc index 873a809616..b28fa2f37e 100644 --- a/src/cpu/x86/32bit/entry32.inc +++ b/src/cpu/x86/32bit/entry32.inc @@ -13,6 +13,7 @@ */ .align 4 +.globl __protected_start __protected_start: /* Save the BIST value */ movl %eax, %ebp diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc index cd73b72fe3..393506b8e3 100644 --- a/src/cpu/x86/Makefile.inc +++ b/src/cpu/x86/Makefile.inc @@ -8,6 +8,8 @@ ramstage-y += backup_default_smm.c subdirs-$(CONFIG_CPU_INTEL_COMMON_SMM) += ../intel/smm +bootblock-y += entry16.S + additional-dirs += $(obj)/cpu/x86 SIPI_ELF=$(obj)/cpu/x86/sipi_vector.elf diff --git a/src/cpu/x86/entry16.S b/src/cpu/x86/entry16.S new file mode 100644 index 0000000000..1ecd6ed422 --- /dev/null +++ b/src/cpu/x86/entry16.S @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +/* + * This software and ancillary information (herein called SOFTWARE) + * called LinuxBIOS is made available under the terms described here. + * + * The SOFTWARE has been approved for release with associated + * LA-CC Number 00-34. Unless otherwise indicated, this SOFTWARE has + * been authored by an employee or employees of the University of + * California, operator of the Los Alamos National Laboratory under + * Contract No. W-7405-ENG-36 with the U.S. Department of Energy. + * + * The U.S. Government has rights to use, reproduce, and distribute this + * SOFTWARE. The public may copy, distribute, prepare derivative works + * and publicly display this SOFTWARE without charge, provided that this + * Notice and any statement of authorship are reproduced on all copies. + * + * Neither the Government nor the University makes any warranty, express + * or implied, or assumes any liability or responsibility for the use of + * this SOFTWARE. If SOFTWARE is modified to produce derivative works, + * such modified SOFTWARE should be clearly marked, so as not to confuse + * it with the version available from LANL. + * + */ + + +/* Start code to put an i386 or later processor into 32-bit protected mode. + */ + +#include +#include + +.section .init._start, "ax", @progbits + +/* Symbol _start16bit must reachable from the reset vector, and be aligned to + * 4kB to start AP CPUs with Startup IPI message without RAM. + */ +.align 4096 +.code16 +.globl _start16bit +.type _start16bit, @function + +_start16bit: + cli + /* Save the BIST result */ + movl %eax, %ebp +#if !CONFIG(NO_EARLY_BOOTBLOCK_POSTCODES) + post_code(POST_RESET_VECTOR_CORRECT) +#endif + + /* IMMEDIATELY invalidate the translation lookaside buffer (TLB) 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. Thanks to kmliu@sis.com.tw for this TLB fix. + */ + + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB*/ + + /* Invalidating the cache here seems to be a bad idea on + * modern processors. Don't. + * If we are hyperthreaded or we have multiple cores it is bad, + * for SMP startup. On Opterons it causes a 5 second delay. + * Invalidating the cache was pure paranoia in any event. + * If your CPU needs it you can write a CPU dependent version of + * entry16.inc. + */ + + /* Note: gas handles memory addresses in 16 bit code very poorly. + * In particular it doesn't appear to have a directive allowing you + * associate a section or even an absolute offset with a segment register. + * + * This means that anything except cs:ip relative offsets are + * a real pain in 16 bit mode. And explains why it is almost + * impossible to get gas to do lgdt correctly. + * + * One way to work around this is to have the linker do the + * math instead of the assembler. This solves the very + * practical problem of being able to write code that can + * be relocated. + * + * An lgdt call before we have memory enabled cannot be + * position independent, as we cannot execute a call + * instruction to get our current instruction pointer. + * So while this code is relocatable it isn't arbitrarily + * relocatable. + * + * The criteria for relocation have been relaxed to their + * utmost, so that we can use the same code for both + * our initial entry point and startup of the second CPU. + * The code assumes when executing at _start16bit that: + * (((cs & 0xfff) == 0) and (ip == _start16bit & 0xffff)) + * or + * ((cs == anything) and (ip == 0)). + * + * The restrictions in reset16.inc mean that _start16bit initially + * must be loaded at or above 0xffff0000 or below 0x100000. + * + * The linker scripts computes gdtptr16_offset by simply returning + * the low 16 bits. This means that the initial segment used + * when start is called must be 64K aligned. This should not + * restrict the address as the ip address can be anything. + * + * Also load an IDT with NULL limit to prevent the 16bit IDT being used + * in protected mode before c_start.S sets up a 32bit IDT when entering + * RAM stage. In practise: CPU will shutdown on any exception. + * See IA32 manual Vol 3A 19.26 Interrupts. + */ + + movw %cs, %ax + shlw $4, %ax + movw $nullidt_offset, %bx + subw %ax, %bx + lidt %cs:(%bx) + movw $gdtptr_offset, %bx + subw %ax, %bx + lgdtl %cs:(%bx) + + 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 to %eax */ + movl %ebp, %eax + + /* Now that we are in protected mode jump to a 32 bit code segment. */ + ljmpl $ROM_CODE_SEG, $__protected_start + + /** + * The gdt is defined in gdt_init.S, it has a 4 Gb code segment + * at 0x08, and a 4 GB data segment at 0x10; + */ +__gdtptr: + .long gdtptr + +.align 4 +.globl nullidt +nullidt: + .word 0 /* limit */ + .long 0 + .word 0 -- cgit v1.2.3