arch/x86: Unify GDT entries

Currently there are 3 GDTs (Global Descriptor Tables) being used on x86:
- preRAM (gdt_init.S)
- SMM (smm_stub.S)
- RAM (c_start.S)

They have different layouts and thus different offsets for the segments
being used in assembly code. Stop using different GDT segments and
ensure that for ROM (preRAM + SMM) and RAM (ramstage) the segments
match. RAM will have additional entries, not found in pre RAM GDT,
but the segments for protected mode and 64-bit mode now match in
all stages.

This allows to use the same defines in all stages. It also drops the
need to know in which stage the code is compiled and it's no longer
necessary to switch the code segment between stages.

While at it fix the comments in the ramstage GDT and drop unused
declarations from header files, always set the accessed bit and drop
GDT_CODE_ACPI_SEG.

Change-Id: I208496e6e4cc82833636f4f42503b44b0d702b9e
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87255
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Shuo Liu <shuo.liu@intel.com>
Reviewed-by: Maximilian Brune <maximilian.brune@9elements.com>
This commit is contained in:
Patrick Rudolph 2025-04-10 08:51:55 +02:00 committed by Matt DeVillier
commit a6be271e63
14 changed files with 89 additions and 135 deletions

View file

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <cpu/x86/gdt.h>
#include <cpu/x86/post_code.h>
#include <arch/ram_segs.h>
/* Place the stack in the bss section. It's not necessary to define it in
* the linker script. */
@ -30,9 +30,9 @@ _start:
lgdt (%rax)
#else
lgdt %cs:gdtaddr
ljmp $RAM_CODE_SEG, $1f
ljmp $GDT_CODE_SEG, $1f
#endif
1: movl $RAM_DATA_SEG, %eax
1: movl $GDT_DATA_SEG, %eax
movl %eax, %ds
movl %eax, %es
movl %eax, %ss
@ -40,7 +40,7 @@ _start:
movl %eax, %fs
movl %eax, %gs /* Will be used for cpu_info */
#if ENV_X86_64
mov $RAM_CODE_SEG64, %ecx
mov $GDT_CODE_SEG64, %ecx
call SetCodeSelector
#endif
@ -152,46 +152,44 @@ gdtaddr:
.data
/* This is the gdt for GCC part of coreboot.
/*
* This is the gdt for coreboot's ramstage.
* It is different from the gdt in ASM part of coreboot
* which is defined in gdt_init.S
*
* When the machine is initially started, we use a very simple
* gdt from ROM (that in gdt_init.S) which only contains those
* entries we need for protected mode.
* entries we need for protected mode and long mode.
*
* When we're executing code from RAM, we want to do more complex
* stuff, like initializing PCI option ROMs in real mode, or doing
* a resume from a suspend to RAM.
* a resume from a suspend to RAM, which happens in real mode.
*
* Keep in sync with 'cpu/x86/gdt.h'.
*/
gdt:
/* selgdt 0, unused */
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
/* selgdt 8, unused */
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
/* selgdt 0x10, flat code segment */
/* selgdt 0x08, flat code segment */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
* limit
*/
.byte 0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes
for limit */
/* selgdt 0x18, flat data segment */
/* selgdt 0x10, flat data segment */
.word 0xffff, 0x0000
#if ENV_X86_64
.byte 0x00, 0x92, 0xcf, 0x00
#else
.byte 0x00, 0x93, 0xcf, 0x00
#endif
/* selgdt 0x20, unused */
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x00, 0x00, 0x00
/* selgdt 0x18, flat code segment (64-bit) */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xaf, 0x00
/* The next two entries are used for executing VGA option ROMs */
/* gdt selector 0x20 tss segment, used by STM */
.word 0xffff, 0x0000
.byte 0x00, 0x8b, 0x80, 0x00
/* The next two entries are used for executing ACPI S3 RESUME and VGA option ROMs */
/* selgdt 0x28 16 bit 64k code at 0x00000000 */
.word 0xffff, 0x0000
@ -201,34 +199,25 @@ gdt:
.word 0xffff, 0x0000
.byte 0, 0x92, 0, 0
/* The next two entries are used for ACPI S3 RESUME */
/* The next entry is used for VGA option ROMs. See x86_asm.S */
/* selgdt 0x38, flat data segment 16 bit */
.word 0x0000, 0x0000 /* dummy */
.byte 0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
* limit
*/
/* selgdt 0x40, flat code segment 16 bit */
/*
* selgdt 0x38, flat code segment 16 bits
*
* FIXME: It's only used in %ds (therefore used like a data segment).
* The PCI Specification doesn't enforce this.
* Is this a workaround for broken Option ROMs?
*/
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for
* limit
*/
#if ENV_X86_64
/* selgdt 0x48, flat x64 code segment */
.word 0xffff, 0x0000
.byte 0x00, 0x9b, 0xaf, 0x00
#endif
per_cpu_segment_descriptors:
.rept CONFIG_MAX_CPUS
/* flat data segment */
.word 0xffff, 0x0000
#if ENV_X86_64
.byte 0x00, 0x92, 0xcf, 0x00
#else
.byte 0x00, 0x93, 0xcf, 0x00
#endif
.endr
gdt_end:

View file

@ -1,14 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef RAM_SEGS_H
#define RAM_SEGS_H
#define RAM_CODE_SEG 0x10
#define RAM_DATA_SEG 0x18
#define RAM_CODE16_SEG 0x28
#define RAM_DATA16_SEG 0x30
#define RAM_CODE_ACPI_SEG 0x38
#define RAM_DATA_ACPI_SEG 0x40
#define RAM_CODE_SEG64 0x48
#endif /* RAM_SEGS_H */

View file

@ -1,17 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef ROM_SEGS_H
#define ROM_SEGS_H
#define ROM_CODE_SEG 0x08
#define ROM_DATA_SEG 0x10
#define ROM_CODE_SEG64 0x18
/*
* This define is placed here to make sure future romstage programmers
* know about it.
* It is used for STM setup code.
*/
#define SMM_TASK_STATE_SEG 0x20
#endif /* ROM_SEGS_H */

View file

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/ram_segs.h>
#include <cpu/x86/gdt.h>
#define WAKEUP_BASE 0x600
#define RELOCATED(x) (x - __wakeup + WAKEUP_BASE)
@ -31,7 +31,7 @@ __wakeup:
add $8, %rax
push %rax
pushfq
push $RAM_CODE_SEG
push $GDT_CODE_SEG
lea 3(%rip), %rax
push %rax
iretq
@ -60,7 +60,7 @@ __wakeup:
movw %ax, (__wakeup_segment)
/* Activate the right segment descriptor real mode. */
ljmp $RAM_CODE16_SEG, $RELOCATED(1f)
ljmp $GDT_CODE16_SEG, $RELOCATED(1f)
1:
.code16
/* 16 bit code from here on... */
@ -70,7 +70,7 @@ __wakeup:
* configurations (limits, writability, etc.) once
* protected mode is turned off.
*/
mov $RAM_DATA16_SEG, %ax
mov $GDT_DATA16_SEG, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs