diff --git a/Documentation/arch/x86/index.md b/Documentation/arch/x86/index.md index f5546d18d5..81eb51925a 100644 --- a/Documentation/arch/x86/index.md +++ b/Documentation/arch/x86/index.md @@ -46,7 +46,7 @@ At the moment *$n* is 4, which results in identity mapping the lower 4 GiB. * Setup page tables for long mode - *DONE* * Add assembly code for long mode - *DONE* * Add assembly code for SMM - *DONE* -* Add assembly code for postcar stage - *TODO* +* Add assembly code for postcar stage - *DONE* * Add assembly code to return to protected mode - *TODO* * Implement reference code for mainboard `emulation/qemu-q35` - *TODO* diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc index 17ab3dc9b9..5bba47f0b5 100644 --- a/src/arch/x86/Makefile.inc +++ b/src/arch/x86/Makefile.inc @@ -195,7 +195,11 @@ endif # CONFIG_ARCH_ROMSTAGE_X86_32 / CONFIG_ARCH_ROMSTAGE_X86_64 # postcar ############################################################################### +ifeq ($(CONFIG_ARCH_POSTCAR_X86_32),y) $(eval $(call create_class_compiler,postcar,x86_32)) +else +$(eval $(call create_class_compiler,postcar,x86_64)) +endif postcar-generic-ccopts += -D__POSTCAR__ postcar-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c diff --git a/src/arch/x86/exit_car.S b/src/arch/x86/exit_car.S index a921ee5d7d..806dc9c069 100644 --- a/src/arch/x86/exit_car.S +++ b/src/arch/x86/exit_car.S @@ -10,6 +10,30 @@ post_car_stack_top: .long 0 .long 0 +#if defined(__x86_64__) +.code64 +.macro pop_eax_edx + pop %rax + mov %rax, %rdx + shr $32, %rdx +.endm +.macro pop_ebx_esi + pop %rbx + mov %rbx, %rsi + shr $32, %rsi +.endm +#else +.code32 +.macro pop_eax_edx + pop %eax + pop %edx +.endm +.macro pop_ebx_esi + pop %ebx + pop %esi +.endm +#endif + .text .global _start _start: @@ -17,7 +41,11 @@ _start: is expected to be implemented in assembly. */ /* Migrate GDT to this text segment */ +#if defined(__x86_64__) + call gdt_init64 +#else call gdt_init +#endif #ifdef __x86_64__ mov %rdi, _cbmem_top_ptr @@ -31,10 +59,15 @@ _start: call chipset_teardown_car /* Enable caching if not already enabled. */ +#ifdef __x86_64__ + mov %cr0, %rax + and $(~(CR0_CD | CR0_NW)), %eax + mov %rax, %cr0 +#else mov %cr0, %eax and $(~(CR0_CD | CR0_NW)), %eax mov %eax, %cr0 - +#endif /* Ensure cache is clean. */ invd @@ -61,8 +94,13 @@ _start: /* Need to align stack to 16 bytes at the call instruction. Therefore account for the 1 push. */ andl $0xfffffff0, %esp +#if defined(__x86_64__) + mov %rbp, %rdi +#else sub $12, %esp push %ebp +#endif + call soc_set_mtrrs /* Ignore fixing up %esp since we're setting it a new value. */ @@ -73,7 +111,7 @@ _start: call soc_enable_mtrrs #else /* CONFIG_SOC_SETS_MSRS */ /* Clear variable MTRRs. */ - pop %ebx /* Number to clear */ + pop_ebx_esi /* ebx: Number to clear, esi: Number to set */ test %ebx, %ebx jz 2f xor %eax, %eax @@ -89,23 +127,20 @@ _start: 2: /* Set Variable MTRRs based on stack contents. */ - pop %ebx /* Number to set. */ - test %ebx, %ebx + test %esi, %esi jz 2f mov $(MTRR_PHYS_BASE(0)), %ecx 1: /* Write MTRR base. */ - pop %eax - pop %edx + pop_eax_edx wrmsr inc %ecx /* Write MTRR mask. */ - pop %eax - pop %edx + pop_eax_edx wrmsr inc %ecx - dec %ebx + dec %esi jnz 1b 2: diff --git a/src/arch/x86/gdt_init.S b/src/arch/x86/gdt_init.S index d90aba64d3..7dd4b94933 100644 --- a/src/arch/x86/gdt_init.S +++ b/src/arch/x86/gdt_init.S @@ -15,6 +15,22 @@ gdtptr: .word gdt_end - gdt -1 /* compute the table limit */ .long gdt /* we know the offset */ +#ifdef __x86_64__ +.code64 +.section ".text._gdt64_", "ax", @progbits + .globl gdt_init64 +gdt_init64: + lgdt gdtptr64 + ret + +.previous + .align 4 +.globl gdtptr64 +gdtptr64: + .word gdt_end - gdt -1 /* compute the table limit */ + .quad gdt /* we know the offset */ +#endif + .align 4 gdt: /* selgdt 0, unused */